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