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 
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