Warning, /include/Geant4/tools/rroot/buffer is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_rroot_buffer
0005 #define tools_rroot_buffer
0006
0007 #include "rbuf"
0008 #include "ifac"
0009 #include "iro"
0010 #include "../sout"
0011 #include "../mapmanip"
0012 #ifdef TOOLS_MEM
0013 #include "../mem"
0014 #endif
0015
0016 #include <string>
0017 #include <vector>
0018 #include <ostream>
0019
0020 // in TOOLS_STL, we don't have (yet) a performant map.
0021
0022 #ifdef tools_stl_vector
0023 #define TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0024 //#define TOOLS_RROOT_OBJ_MAP_OMAP
0025 #else
0026 #define TOOLS_RROOT_OBJ_MAP_STD_MAP
0027 #endif
0028
0029 #ifdef TOOLS_RROOT_OBJ_MAP_STD_MAP
0030 #include <map>
0031 #endif
0032 #ifdef TOOLS_RROOT_OBJ_MAP_OMAP
0033 #include "../omap"
0034 #endif
0035 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0036 #include "../hash_table"
0037 #include "../hash"
0038 #endif
0039
0040 namespace tools {
0041 namespace rroot {
0042
0043 class buffer : public rbuf {
0044 typedef rbuf parent;
0045
0046 static const std::string& s_class() {
0047 static const std::string s_v("tools::rroot::buffer");
0048 return s_v;
0049 }
0050
0051 #ifdef TOOLS_RROOT_OBJ_MAP_STD_MAP
0052 typedef std::map<uint32,iro*> obj_map;
0053 #endif
0054 #ifdef TOOLS_RROOT_OBJ_MAP_OMAP
0055 typedef omap<uint32,iro*> obj_map;
0056 #endif
0057 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0058 class obj_map : public hash_table<uint32,iro*> {
0059 typedef hash_table<uint32,iro*> parent;
0060 protected:
0061 virtual unsigned int hash(const uint32& a_key) {
0062 return hash(&a_key,sizeof(uint32));
0063 }
0064 virtual bool cmp(const uint32& a_key1,const uint32& a_key2) {
0065 return a_key1==a_key2?true:false;
0066 }
0067 public:
0068 obj_map():parent(){}
0069 virtual ~obj_map(){}
0070 private:
0071 obj_map(const obj_map& a_from):parent(a_from){}
0072 obj_map& operator=(const obj_map& a_from){
0073 parent::operator=(a_from);
0074 return *this;
0075 }
0076 };
0077 #endif
0078
0079 public:
0080 buffer(std::ostream& a_out,bool a_byte_swap,uint32 a_size,char* a_buffer,uint32 a_klen,bool a_verbose)
0081 :parent(a_out,a_byte_swap,a_buffer+a_size,m_pos)
0082 ,m_byte_swap(a_byte_swap)
0083 ,m_verbose(a_verbose)
0084 //,m_verbose(true)
0085 ,m_size(a_size) //expect a not zero size.
0086 ,m_buffer(a_buffer) //don't get ownership.
0087 ,m_pos(a_buffer)
0088 ,m_klen(a_klen) //to compute refs (used in read_class, read_object)
0089 //,m_map_objs(false)
0090 ,m_map_objs(true)
0091 {
0092 #ifdef TOOLS_MEM
0093 mem::increment(s_class().c_str());
0094 #endif
0095 }
0096 virtual ~buffer(){
0097 m_objs.clear();
0098 #ifdef TOOLS_MEM
0099 mem::decrement(s_class().c_str());
0100 #endif
0101 }
0102 protected:
0103 buffer(const buffer& a_from)
0104 :parent(a_from.m_out,a_from.m_byte_swap,0,m_pos)
0105 ,m_byte_swap(a_from.m_byte_swap)
0106 ,m_map_objs(a_from.m_map_objs)
0107 {
0108 #ifdef TOOLS_MEM
0109 mem::increment(s_class().c_str());
0110 #endif
0111 }
0112 buffer& operator=(const buffer&){return *this;}
0113 public:
0114 bool byte_swap() const {return m_byte_swap;}
0115 bool verbose() const {return m_verbose;}
0116
0117 void set_offset(unsigned int a_off) {m_pos = m_buffer+a_off;}
0118
0119 //char* buffer() const {return m_buffer;}
0120 uint32 length() const {return uint32(m_pos-m_buffer);}
0121 uint32 size() const {return m_size;}
0122
0123 void set_map_objs(bool a_value) {m_map_objs = a_value;}
0124 bool map_objs() const {return m_map_objs;}
0125 protected:
0126 // on first_int :
0127 static uint32 kNullTag() {return 0;}
0128 static uint32 kByteCountMask() {return 0x40000000;}
0129 // on tag :
0130 static uint32 kNewClassTag() {return 0xFFFFFFFF;}
0131 static uint32 kClassMask() {return 0x80000000; }
0132 static uint32 kMapOffset() {return 2;}
0133 static short kByteCountVMask() {return 0x4000;}
0134
0135 bool read_class_tag(std::string& a_class) {
0136 a_class.clear();
0137
0138 uint32 tag;
0139 if(!parent::read(tag)) return false;
0140
0141 if(tag==kNewClassTag()) {
0142 char _s[80];
0143 if(!read_string(_s, 80)) {
0144 m_out << "tools::rroot::read_class_tag :"
0145 << " read string." << std::endl;
0146 return false;
0147 }
0148 //m_out << "tools::rroot::read_class_tag :"
0149 // << " tag kNewClassTag"
0150 // << " class " << _s
0151 // << std::endl;
0152 a_class = _s;
0153 return true;
0154
0155 } else if(tag & kClassMask()) {
0156 //m_out << "tools::rroot::read_class_tag :"
0157 // << " tag & kClassMask"
0158 // << " ref " << (uint32)(tag & ~kClassMask)
0159 // << " recurse..."
0160 // << std::endl;
0161
0162 unsigned int cl_offset = (tag & ~kClassMask());
0163 cl_offset -= kMapOffset();
0164 cl_offset -= m_klen;
0165 char* old_pos = m_pos;
0166 m_pos = m_buffer + cl_offset;
0167 //std::string scls;
0168 //uint32 ref;
0169 if(!read_class_tag(a_class)) return false;
0170 m_pos = old_pos;
0171
0172 return true;
0173
0174 } else {
0175
0176 std::ios::fmtflags old_flags = m_out.flags();
0177 m_out << "tools::rroot::read_class_tag :"
0178 << " tag unknown case ! "
0179 << tag << " hex " << std::hex << tag
0180 << std::endl;
0181 m_out.flags(old_flags);
0182
0183 return false;
0184 }
0185 }
0186
0187 bool read_class(std::string& a_class,uint32& a_bcnt,bool& a_is_ref){
0188 //m_verbose = true;
0189 a_class.clear();
0190 a_bcnt = 0;
0191 a_is_ref = false;
0192
0193 //uint32 fVersion = 0; //Buffer format version
0194
0195 // read byte count and/or tag (older files don't have byte count)
0196 uint32 first_int = 0;
0197 if(!parent::read(first_int)) return false;
0198
0199 if(m_verbose) {
0200 std::ios::fmtflags old_flags = m_out.flags();
0201 m_out << "tools::rroot::read_class :"
0202 << " first_int " << std::hex << first_int
0203 << std::endl;
0204 m_out.flags(old_flags);
0205 }
0206
0207 if(first_int==kNullTag()) { //GB
0208 if(m_verbose) {
0209 m_out << "tools::rroot::read_class :"
0210 << " first_int is kNullTag."
0211 << std::endl;
0212 }
0213 a_bcnt = 0;
0214 return true;
0215
0216 //} else if(first_int==kNewClassTag()) { // class desc follows.
0217 } else if(first_int & kByteCountMask()) {
0218 // at write :
0219 // skip int to store bcnt.
0220 // + write class
0221 // if(!write((clIdx | Rio_kClassMask))) return false;
0222 // or
0223 // if(!write(Rio_kNewClassTag)) return false;
0224 // + write object
0225 // + set byte cnt (cnt|kByteCountMask()) at skipped int.
0226
0227 if(m_verbose) {
0228 m_out << "tools::rroot::read_class :"
0229 << " first_int & kByteCountMask."
0230 << std::endl;
0231 }
0232
0233 uint32 bef_tag = uint32(m_pos-m_buffer);
0234 //fVersion = 1;
0235
0236 std::string scls;
0237 if(!read_class_tag(scls)) return false;
0238 if(scls.empty()) {
0239 m_out << "tools::rroot::buffer::read_class :"
0240 << " read_class_tag did not find a class name."
0241 << std::endl;
0242 return false;
0243 }
0244
0245 a_class = scls;
0246 a_bcnt = (first_int & ~kByteCountMask());
0247
0248 if(m_verbose) {
0249 m_out << "tools::rroot::read_class :"
0250 << " kNewClassTag : read class name " << sout(a_class)
0251 << " a_bcnt " << a_bcnt
0252 << " bef_tag " << bef_tag
0253 << "." << std::endl;
0254 }
0255
0256 return true;
0257
0258 } else {
0259 if(m_verbose) {
0260 std::ios::fmtflags old_flags = m_out.flags();
0261 m_out << "tools::rroot::read_class :"
0262 << " first_int " << std::hex << first_int
0263 << ". first_int is position toward object."
0264 << std::endl;
0265 m_out.flags(old_flags);
0266 }
0267 a_bcnt = first_int; //pos toward object.
0268 a_is_ref = true;
0269 a_class.clear();
0270 return true;
0271 }
0272
0273 return false;
0274 }
0275 public:
0276 void remove_in_map(iro* a_obj) {
0277 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0278 m_out << "tools::rroot::remove_in_map : dummy." << std::endl;
0279 #else
0280 find_and_remove_value(m_objs,a_obj);
0281 #endif
0282 }
0283 bool read_object(ifac& a_fac,const ifac::args& a_args,iro*& a_obj,bool& a_created){
0284 a_obj = 0;
0285 a_created = false;
0286
0287 //m_out << "debug : tools::rroot::buffer::read_object : begin :" << std::endl;
0288
0289 // before reading object save start position
0290 uint32 startpos = (uint32)(m_pos-m_buffer);
0291
0292 uint32 bcnt;
0293 std::string sclass;
0294 bool is_ref;
0295 if(!read_class(sclass,bcnt,is_ref)) {
0296 m_out << "tools::rroot::buffer::read_object :"
0297 << " can't read class." << std::endl;
0298 return false;
0299 }
0300 //::printf("debug : %d\n",length()-startpos);
0301
0302 if(m_verbose) {
0303 m_out << "tools::rroot::buffer::read_object :"
0304 << " class " << sout(sclass) << ", is_ref " << is_ref
0305 << ", bcnt " << bcnt
0306 << std::endl;
0307 }
0308
0309 if(is_ref) { //bcnt is the position toward an object or an object ref.
0310 //m_out << "debug : tools::rroot::buffer::read_object : is_ref : bcnt " << bcnt << std::endl;
0311
0312 unsigned int obj_offset = bcnt;
0313 obj_offset -= kMapOffset();
0314 obj_offset -= m_klen;
0315
0316 if(!m_map_objs) {
0317 m_out << "tools::rroot::buffer::read_object : warning :"
0318 << " class " << sout(sclass) << ", is_ref but map objs is not enabled on this buffer."
0319 << std::endl;
0320 }
0321
0322 if(m_map_objs) {
0323 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0324 if(m_objs.find(obj_offset,a_obj)) {
0325 //m_out << "debug : tools::rroot::buffer::read_object : found object in map." << bcnt << std::endl;
0326 return true;
0327 }
0328 #else
0329 obj_map::const_iterator it = m_objs.find(obj_offset);
0330 if(it!=m_objs.end()) {
0331 a_obj = (*it).second;
0332 //::printf("debug : find : %d %lu\n",obj_offset,a_obj);
0333 //stay at current m_pos ?
0334 return true;
0335 }
0336 #endif
0337 }
0338
0339 {char* old_pos = m_pos;
0340
0341 m_pos = m_buffer + obj_offset;
0342
0343 uint32 first_int;
0344 if(!parent::read(first_int)) {
0345 m_out << "tools::rroot::buffer::read_object : parent::read(first_int) failed." << std::endl;
0346 return false;
0347 }
0348 if(first_int & kByteCountMask()) {
0349 std::string scls;
0350 if(!read_class_tag(scls)) {
0351 m_out << "tools::rroot::buffer::read_object : read_class_tag() failed." << std::endl;
0352 return false;
0353 }
0354 if(scls.empty()) {
0355 m_out << "tools::rroot::buffer::read_object :"
0356 << " read_class_tag did not find a class name."
0357 << std::endl;
0358 return false;
0359 }
0360
0361 //m_out << "tools::rroot::buffer::read_object :"
0362 // << " is_ref : class " << sout(scls)
0363 // << std::endl;
0364
0365 iro* obj = a_fac.create(scls,a_args);
0366 if(!obj) {
0367 m_out << "tools::rroot::buffer::read_object : is_ref : creation of object"
0368 << " of class " << sout(sclass) << " failed." << std::endl;
0369 return false;
0370 }
0371
0372 if(m_map_objs) {
0373 //must be done before stream()
0374 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0375 if(!m_objs.insert(obj_offset,obj)) {
0376 m_out << "tools::rroot::buffer::read_object :"
0377 << " map insert failed."
0378 << std::endl;
0379 }
0380 #else
0381 m_objs[obj_offset] = obj;
0382 #endif
0383 }
0384
0385 if(!obj->stream(*this)) {
0386 m_out << "tools::rroot::buffer::read_object :"
0387 << " is_ref : streamed failed for class " << sout(scls)
0388 << std::endl;
0389 //restore a good buffer position :
0390 //m_pos = m_buffer+startpos+sizeof(unsigned int);
0391 delete obj;
0392 return false;
0393 }
0394
0395 //m_out << "tools::rroot::buffer::read_object :"
0396 // << " is_ref : streamed ok for class " << sout(scls)
0397 // << std::endl;
0398
0399 a_obj = obj;
0400 a_created = true;
0401
0402 } else {
0403 m_out << "tools::rroot::buffer::read_object :"
0404 << " is_ref : zzz"
0405 << std::endl;
0406 }
0407
0408 m_pos = old_pos;}
0409
0410 // in principle at this point m_pos should be
0411 // m_buffer+startpos+sizeof(unsigned int)
0412 // but enforce it anyway :
0413 m_pos = m_buffer+startpos+sizeof(unsigned int);
0414 //check_byte_count(startpos,0,sclass) would always be ok.
0415
0416 //a_obj = ???
0417
0418 } else {
0419 if(sclass.empty()) {
0420 //m_out << "debug : tools::rroot::buffer::read_object : found empty class name." << std::endl;
0421
0422 m_pos = m_buffer+startpos+bcnt+sizeof(unsigned int);
0423
0424 } else {
0425 //m_out << "debug : tools::rroot::buffer::read_object : not a ref, create object." << std::endl;
0426
0427 // Being not a ref, it must NOT be in the map.
0428 // We gain a lot by not doing the below find.
0429 /*
0430 if(m_map_objs) {
0431 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0432 if(m_objs.find(startpos,a_obj)) return true;
0433 #else
0434 obj_map::const_iterator it = m_objs.find(startpos);
0435 if(it!=m_objs.end()) {
0436 a_obj = (*it).second;
0437 ::printf("debug : find xxx : %d %lu\n",startpos,a_obj);
0438 //stay at current m_pos ?
0439 return true;
0440 }
0441 #endif
0442 }
0443 */
0444
0445 iro* obj = a_fac.create(sclass,a_args);
0446 if(!obj) {
0447 m_out << "tools::rroot::buffer::read_object : creation of object"
0448 << " of class " << sout(sclass) << " failed." << std::endl;
0449 return false;
0450 }
0451 //m_out << "debug : tools::rroot::buffer::read_object : object created." << std::endl;
0452
0453 if(m_map_objs) {
0454 //must be done before stream()
0455 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
0456 if(!m_objs.insert(startpos,obj)) {
0457 m_out << "tools::rroot::buffer::read_object :"
0458 << " map insert failed."
0459 << std::endl;
0460 }
0461 #else
0462 m_objs[startpos] = obj;
0463 #endif
0464 }
0465
0466 //::printf("debug : map : %d %lu\n",startpos,obj);
0467
0468 //NOTE : if class ref, "up there"-startpos = 8.
0469 if(!obj->stream(*this)) {
0470 m_out << "tools::rroot::buffer::read_object : object.stream() failed"
0471 << " for object of class " << sout(sclass) << "." << std::endl;
0472 //restore a good buffer position :
0473 //m_pos = m_buffer+startpos+bcnt+sizeof(unsigned int);
0474 delete obj;
0475 return false;
0476 }
0477
0478 //NOTE : if obj stream ok, the below line is not needed.
0479 //m_pos = m_buffer+startpos+bcnt+sizeof(unsigned int);
0480
0481 if(!check_byte_count(startpos,bcnt,sclass)) {
0482 m_out << "tools::rroot::buffer::read_object :"
0483 << " check_byte_count failed "
0484 << "for object of class "
0485 << sout(sclass) << "." << std::endl;
0486 delete obj;
0487 return false;
0488 }
0489
0490 a_obj = obj;
0491 a_created = true;
0492 }
0493
0494 }
0495
0496 if(m_verbose) {
0497 m_out << "tools::rroot::buffer::read_object : end." << std::endl;
0498 }
0499
0500 return true;
0501 }
0502 public:
0503 bool read_version(short& a_version){
0504 // Read class version from I/O buffer.
0505 // Is read a short or three shorts.
0506 a_version = 0;
0507 short version = 0;
0508 // not interested in byte count
0509 if(!parent::read(version)) return false;
0510
0511 // if this is a byte count, then skip next short and read version
0512 if(version & kByteCountVMask()) {
0513 if(!parent::read(version)) return false;
0514 if(!parent::read(version)) return false;
0515 }
0516
0517 a_version = version;
0518 return true;
0519 }
0520
0521 bool read_version(short& a_version,uint32& a_start_pos,uint32& a_byte_count){
0522 // Read class version from I/O buffer.
0523 // Is read one or three shorts.
0524 a_version = 0;
0525 a_start_pos = 0;
0526 a_byte_count = 0;
0527
0528 short version = 0;
0529
0530 // before reading object save start position
0531 uint32 startpos = (uint32)(m_pos-m_buffer);
0532
0533 // read byte count (older files don't have byte count)
0534 // byte count is packed in two individual shorts, this to be
0535 // backward compatible with old files that have at this location
0536 // only a single short (i.e. the version)
0537 union {
0538 unsigned int cnt;
0539 short vers[2];
0540 } v;
0541
0542 if(m_byte_swap) {
0543 if(!parent::read(v.vers[1])) return false;
0544 if(!parent::read(v.vers[0])) return false;
0545 } else {
0546 if(!parent::read(v.vers[0])) return false;
0547 if(!parent::read(v.vers[1])) return false;
0548 }
0549
0550 // no bytecount, backup and read version
0551 uint32 bcnt = 0;
0552 if(v.cnt & kByteCountMask()) {
0553 bcnt = (v.cnt & ~kByteCountMask());
0554 } else {
0555 m_pos -= sizeof(unsigned int);
0556 }
0557 if(!parent::read(version)) return false;
0558 //printf("Reading version=%d at pos=%d, bytecount=%d\n",
0559 //version,*startpos,*bcnt);
0560
0561 a_version = version;
0562 a_start_pos = startpos;
0563 a_byte_count = bcnt;
0564
0565 return true;
0566 }
0567
0568 bool check_byte_count(uint32 a_start_pos,uint32 a_byte_count,const std::string& a_store_cls){
0569 if(!a_byte_count) return true;
0570
0571 size_t len = a_start_pos + a_byte_count + sizeof(unsigned int);
0572
0573 size_t diff = size_t(m_pos-m_buffer);
0574
0575 if(diff==len) return true;
0576
0577 if(diff<len) {
0578 m_out << "tools::rroot::buffer::check_byte_count :"
0579 << " object of class " << sout(a_store_cls)
0580 << " read too few bytes ("
0581 << long_out(long(len-diff)) << " missing)."
0582 << std::endl;
0583 }
0584 if(diff>len) {
0585 m_out << "tools::rroot::buffer::check_byte_count :"
0586 << " object of class " << sout(a_store_cls)
0587 << " read too many bytes ("
0588 << long_out(long(diff-len)) << " in excess)." << std::endl;
0589 }
0590
0591 m_out << "tools::rroot::buffer::check_byte_count :"
0592 << " " << sout(a_store_cls)
0593 << " streamer not in sync with data on file, fix streamer."
0594 << std::endl;
0595
0596 m_pos = m_buffer+len;
0597
0598 return false;
0599 }
0600 protected:
0601 bool read_string(char* a_string,uint32 a_max) {
0602 // Read string from I/O buffer. String is read till 0 character is
0603 // found or till max-1 characters are read (i.e. string s has max
0604 // bytes allocated).
0605 int nr = 0;
0606 while (nr < int(a_max-1)) {
0607 char ch;
0608 if(!parent::read(ch)) return false;
0609 // stop when 0 read
0610 if(ch == 0) break;
0611 a_string[nr++] = ch;
0612 }
0613 a_string[nr] = 0;
0614 return true;
0615 }
0616 protected:
0617 // buffer objects cannot be copied or assigned
0618 //void checkCount(unsigned int);
0619 //unsigned int checkObject(unsigned int,const IClass*,bool = false);
0620 protected:
0621 bool m_byte_swap;
0622 bool m_verbose;
0623 uint32 m_size;
0624 char* m_buffer;
0625 char* m_pos;
0626 uint32 m_klen; //GB
0627 bool m_map_objs;
0628 obj_map m_objs;
0629 };
0630
0631 inline bool dummy_TXxx_pointer_stream(buffer& a_buffer,ifac& a_fac) {
0632 ifac::args args;
0633 iro* obj;
0634 bool created;
0635 bool status = a_buffer.read_object(a_fac,args,obj,created);
0636 if(obj) {
0637 if(created) {
0638 if(a_buffer.map_objs()) a_buffer.remove_in_map(obj);
0639 delete obj;
0640 }
0641 }
0642 return status;
0643 }
0644
0645 template <class T>
0646 inline bool pointer_stream(buffer& a_buffer,
0647 ifac& a_fac,ifac::args& a_args,
0648 const std::string& a_T_class,
0649 T*& a_obj,bool& a_created){
0650 iro* obj;
0651 if(!a_buffer.read_object(a_fac,a_args,obj,a_created)) {
0652 a_buffer.out() << "tools::rroot::pointer_stream : read_object failed." << std::endl;
0653 a_obj = 0;
0654 a_created = false;
0655 return false;
0656 }
0657 if(!obj) {
0658 a_obj = 0;
0659 a_created = false;
0660 } else {
0661 a_obj = (T*)obj->cast(a_T_class);
0662 if(!a_obj) {
0663 a_buffer.out() << "tools::rroot::pointer_stream : "
0664 << " tools::cast to " << a_T_class << " failed."
0665 << ". Object is a " << obj->s_cls() << "."
0666 << std::endl;
0667 if(a_created) delete obj;
0668 a_created = false;
0669 return false;
0670 }
0671 }
0672 return true;
0673 }
0674
0675 template <class T>
0676 inline bool pointer_stream(buffer& a_buffer,
0677 ifac& a_fac,ifac::args& a_args,
0678 cid a_T_class,
0679 T*& a_obj,bool& a_created){
0680 iro* obj;
0681 if(!a_buffer.read_object(a_fac,a_args,obj,a_created)) {
0682 a_buffer.out() << "tools::rroot::pointer_stream : read_object failed." << std::endl;
0683 a_obj = 0;
0684 a_created = false;
0685 return false;
0686 }
0687 if(!obj) {
0688 a_obj = 0;
0689 a_created = false;
0690 } else {
0691 a_obj = (T*)obj->cast(a_T_class);
0692 if(!a_obj) {
0693 a_buffer.out() << "tools::rroot::pointer_stream : "
0694 << " tools::cast to " << a_T_class << " failed."
0695 << ". Object is a " << obj->s_cls() << "."
0696 << std::endl;
0697 if(a_created) delete obj;
0698 a_created = false;
0699 return false;
0700 }
0701 }
0702 return true;
0703 }
0704
0705 template <class T>
0706 inline bool pointer_stream(buffer& a_buffer,ifac& a_fac,ifac::args& a_args,T*& a_obj,bool& a_created){
0707 //return pointer_stream(a_buffer,a_fac,a_args,T::s_class(),a_obj,a_created);
0708 return pointer_stream(a_buffer,a_fac,a_args,T::id_class(),a_obj,a_created);
0709 }
0710
0711 template <class T>
0712 inline bool fixed_array_stream(buffer& a_buffer,int a_n,T*& a_v){
0713 delete [] a_v;
0714 a_v = 0;
0715 char is_array;
0716 if(!a_buffer.read(is_array)) return false;
0717 if(!is_array) return true;
0718 if(!a_n) return true;
0719 a_v = new T[a_n];
0720 if(!a_buffer.read_fast_array<T>(a_v,a_n)) {
0721 delete [] a_v;
0722 a_v = 0;
0723 return false;
0724 }
0725 return true;
0726 }
0727
0728 }}
0729
0730 #endif