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