Back to home page

EIC code displayed by LXR

 
 

    


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