Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/wroot/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_wroot_buffer
0005 #define tools_wroot_buffer
0006 
0007 // class used for serializing objects.
0008 
0009 #include "wbuf"
0010 #include "ibo"
0011 
0012 #include "../realloc"
0013 #include "../mnmx"
0014 #include "../forit"
0015 
0016 #ifdef TOOLS_MEM
0017 #include "../mem"
0018 #endif
0019 
0020 #include <string>
0021 #include <vector>
0022 #include <ostream>
0023 #include <map>
0024 
0025 namespace tools {
0026 namespace wroot {
0027 
0028 class buffer {
0029   static const std::string& s_class() {
0030     static const std::string s_v("tools::wroot::buffer");
0031     return s_v;
0032   }
0033 public:
0034   buffer(std::ostream& a_out,bool a_byte_swap,uint32 a_size) // we expect a not zero value for a_size.
0035   :m_out(a_out)
0036   ,m_byte_swap(a_byte_swap)
0037   ,m_size(0)
0038   ,m_buffer(0)
0039   ,m_max(0)
0040   ,m_pos(0)
0041   ,m_wb(a_out,a_byte_swap,0,m_pos) //it holds a ref on m_pos.
0042   {
0043 #ifdef TOOLS_MEM
0044     mem::increment(s_class().c_str());
0045 #endif
0046     m_size = a_size;
0047     m_buffer = new char[m_size];
0048     //if(!m_buffer) {}
0049     m_max = m_buffer+m_size;
0050     m_pos = m_buffer;
0051     m_wb.set_eob(m_max);
0052   }
0053 
0054   virtual ~buffer(){
0055     m_objs.clear();
0056     m_obj_mapped.clear();
0057 
0058     m_clss.clear();
0059     m_cls_mapped.clear();
0060 
0061     delete [] m_buffer;
0062 #ifdef TOOLS_MEM
0063     mem::decrement(s_class().c_str());
0064 #endif
0065   }
0066 protected:
0067   buffer(const buffer& a_from)
0068   :m_out(a_from.m_out)
0069   ,m_byte_swap(a_from.m_byte_swap)
0070   ,m_size(0)
0071   ,m_buffer(0)
0072   ,m_max(0)
0073   ,m_pos(0)
0074   ,m_wb(a_from.m_out,a_from.m_byte_swap,0,m_pos)
0075   {
0076 #ifdef TOOLS_MEM
0077     mem::increment(s_class().c_str());
0078 #endif
0079   }
0080   buffer& operator=(const buffer&){return *this;}
0081 public:
0082   bool byte_swap() const {return m_byte_swap;}
0083   std::ostream& out() const {return m_out;}
0084 
0085   //void set_offset(unsigned int a_off) {m_pos = m_buffer+a_off;}
0086 
0087   char* buf() {return m_buffer;}
0088   const char* buf() const {return m_buffer;}
0089   uint32 length() const {return uint32(m_pos-m_buffer);}
0090   uint32 size() const {return m_size;}
0091 
0092   char*& pos() {return m_pos;}          //used in basket.
0093   char* max_pos() const {return m_max;} //used in basket.
0094 
0095 public:
0096   template <class T>
0097   bool write(T x){
0098     if(m_pos+sizeof(T)>m_max) {
0099       if(!expand2(m_size+sizeof(T))) return false;
0100     }
0101     return m_wb.write(x);
0102   }
0103 
0104   bool write(bool x) {return write<unsigned char>(x?1:0);}
0105 
0106   bool write(const std::string& x) {
0107     uint32 sz = (uint32)(x.size() + sizeof(int) + 1);
0108     if((m_pos+sz)>m_max) {
0109       if(!expand2(m_size+sz)) return false;
0110     }
0111     return m_wb.write(x);
0112   }
0113 
0114   bool write_fast_array(const char* a_a,uint32 a_n) {
0115     if(!a_n) return true;
0116     uint32 l = a_n * sizeof(char);
0117     if((m_pos+l)>m_max) {
0118       if(!expand2(m_size+l)) return false;
0119     }
0120     ::memcpy(m_pos,a_a,l);
0121     m_pos += l;
0122     return true;
0123   }
0124 
0125   bool write_cstring(const char* a_s) {return write_fast_array(a_s,(uint32(::strlen(a_s))+1)*sizeof(char));}
0126 
0127   template <class T>
0128   bool write_fast_array(const T* a_a,uint32 a_n) {
0129     if(!a_n) return true;
0130     uint32 l = a_n * sizeof(T);
0131     if((m_pos+l)>m_max) {
0132       if(!expand2(m_size+l)) return false;
0133     }
0134     return m_wb.write<T>(a_a,a_n);
0135   }
0136 
0137   template <class T>
0138   bool write_fast_array(const std::vector<T>& a_v) {
0139     if(a_v.empty()) return true;
0140     uint32 l = uint32(a_v.size() * sizeof(T));
0141     if((m_pos+l)>m_max) {
0142       if(!expand2(m_size+l)) return false;
0143     }
0144     return m_wb.write<T>(a_v);
0145   }
0146 
0147   template <class T>
0148   bool write_array(const T* a_a,uint32 a_n) {
0149     if(!write(a_n)) return false;
0150     return write_fast_array(a_a,a_n);
0151   }
0152 
0153   template <class T>
0154   bool write_array(const std::vector<T> a_v) {
0155     if(!write((uint32)a_v.size())) return false;
0156     return write_fast_array(a_v);
0157   }
0158 
0159   template <class T>
0160   bool write_array2(const std::vector< std::vector<T> > a_v) {
0161     if(!write((uint32)a_v.size())) return false;
0162     for(unsigned int index=0;index<a_v.size();index++) {
0163       if(!write_array(a_v[index])) return false;
0164     }
0165     return true;
0166   }
0167 
0168 public:
0169   bool write_version(short a_version){
0170     if(a_version>kMaxVersion()) {
0171       m_out << "tools::wroot::buffer::write_version :"
0172             << " version number " << a_version
0173             << " cannot be larger than " << kMaxVersion() << "."
0174             << std::endl;
0175       return false;
0176     }
0177     return write(a_version);
0178   }
0179   bool write_version(short a_version,uint32& a_pos){
0180     // reserve space for leading byte count
0181     a_pos = (uint32)(m_pos-m_buffer);
0182 
0183     //NOTE : the below test is lacking in CERN-ROOT !
0184     if((m_pos+sizeof(unsigned int))>m_max) {
0185       if(!expand2(m_size+sizeof(unsigned int))) return false;
0186     }
0187     m_pos += sizeof(unsigned int);
0188 
0189     if(a_version>kMaxVersion()) {
0190       m_out << "tools::wroot::buffer::write_version :"
0191             << " version number " << a_version
0192             << " cannot be larger than " << kMaxVersion() << "."
0193             << std::endl;
0194       return false;
0195     }
0196     return write(a_version);
0197   }
0198 
0199   bool set_byte_count(uint32 a_pos){
0200     uint32 cnt = (uint32)(m_pos-m_buffer) - a_pos - sizeof(unsigned int);
0201     if(cnt>=kMaxMapCount()) {
0202       m_out << "tools::wroot::buffer::set_byte_count :"
0203             << " bytecount too large (more than "
0204             << kMaxMapCount() << ")."
0205             << std::endl;
0206       return false;
0207     }
0208 
0209     union {
0210       uint32 cnt;
0211       short vers[2];
0212     } v;
0213     v.cnt = cnt;
0214 
0215     char* opos = m_pos;
0216     m_pos = (char*)(m_buffer+a_pos);
0217     if(m_byte_swap) {
0218       if(!m_wb.write(short(v.vers[1]|kByteCountVMask())))
0219         {m_pos = opos;return false;}
0220       if(!m_wb.write(v.vers[0])) {m_pos = opos;return false;}
0221     } else {
0222       if(!m_wb.write(short(v.vers[0]|kByteCountVMask())))
0223         {m_pos = opos;return false;}
0224       if(!m_wb.write(v.vers[1])) {m_pos = opos;return false;}
0225     }
0226     m_pos = opos;
0227 
0228     return true;
0229   }
0230 
0231   bool write_object(const ibo& a_obj){
0232     //GB : if adding a write map logic, think to have a displace_mapped()
0233     //     in basket::write_on_file().
0234 
0235     std::map<ibo*,uint32>::const_iterator it = m_objs.find((ibo*)&a_obj);
0236     if(it!=m_objs.end()) {
0237 
0238       uint32 objIdx = (*it).second;
0239 
0240       unsigned int offset = (unsigned int)(m_pos-m_buffer);
0241 
0242       // save index of already stored object
0243       if(!write(objIdx)) return false;
0244 
0245       m_obj_mapped.push_back(std::pair<uint32,uint32>(offset,objIdx));
0246 
0247     } else {
0248 
0249       // reserve space for leading byte count
0250       uint32 cntpos = (unsigned int)(m_pos-m_buffer);
0251 
0252       //NOTE : the below test is lacking in CERN-ROOT !
0253       if((m_pos+sizeof(unsigned int))>m_max) {
0254         if(!expand2(m_size+sizeof(unsigned int))) return false;
0255       }
0256       m_pos += sizeof(unsigned int);
0257 
0258       // write class of object first
0259       if(!write_class(a_obj.store_cls())) return false;
0260 
0261       // add to map before writing rest of object (to handle self reference)
0262       // (+kMapOffset so it's != kNullTag)
0263       m_objs[(ibo*)&a_obj] = cntpos + kMapOffset();
0264 
0265       // let the object write itself :
0266       if(!a_obj.stream(*this)) return false;
0267 
0268       // write byte count
0269       if(!set_byte_count_obj(cntpos)) return false;
0270     }
0271     return true;
0272   }
0273 
0274   bool expand2(uint32 a_new_size) {return expand(mx<uint32>(2*m_size,a_new_size));} //CERN-ROOT logic.
0275 
0276   bool expand(uint32 a_new_size) {
0277     diff_pointer_t len = m_pos-m_buffer;
0278     if(!realloc<char>(m_buffer,a_new_size,m_size)) {
0279       m_out << "tools::wroot::buffer::expand :"
0280             << " can't realloc " << a_new_size << " bytes."
0281             << std::endl;
0282       m_size = 0;
0283       m_max = 0;
0284       m_pos = 0;
0285       m_wb.set_eob(m_max);
0286       return false;
0287     }
0288     m_size = a_new_size;
0289     m_max = m_buffer + m_size;
0290     m_pos = m_buffer + len;
0291     m_wb.set_eob(m_max);
0292     return true;
0293   }
0294 
0295   size_t to_displace() const {return m_cls_mapped.size()+m_obj_mapped.size();}
0296 
0297   bool displace_mapped(unsigned int a_num){
0298     char* opos = m_pos;
0299 
0300     //m_out << "tools::wroot::buffer::displace_mapped :"
0301     //      << " cls num " << m_cls_mapped.size()
0302     //      << std::endl;
0303 
0304     typedef std::pair<uint32,uint32> offset_id;
0305 
0306    {tools_vforcit(offset_id,m_cls_mapped,it) {
0307       unsigned int offset = (*it).first;
0308       unsigned int id = (*it).second;
0309       //m_out << "displace " << offset << " " << id << std::endl;
0310       m_pos = m_buffer+offset;
0311       unsigned int clIdx = id+a_num;
0312       if(!write(uint32(clIdx|kClassMask()))) {m_pos = opos;return false;}
0313     }}
0314 
0315     //m_out << "tools::wroot::buffer::displace_mapped :"
0316     //      << " obj num " << m_obj_mapped.size()
0317     //      << std::endl;
0318 
0319    {tools_vforcit(offset_id,m_obj_mapped,it) {
0320       uint32 offset = (*it).first;
0321       uint32 id = (*it).second;
0322       //m_out << "displace at " << offset
0323       //      << " the obj pos " << id
0324       //      << " by " << a_num
0325       //      << std::endl;
0326       m_pos = m_buffer+offset;
0327       unsigned int objIdx = id+a_num;
0328       if(!write(objIdx)) {m_pos = opos;return false;}
0329     }}
0330 
0331     m_pos = opos;
0332     return true;
0333   }
0334 
0335   void reset_objs_map() {
0336     m_objs.clear();
0337     //m_clss.clear();
0338   }
0339 protected:
0340   static short kMaxVersion() {return 0x3FFF;}
0341   static uint32 kMaxMapCount() {return 0x3FFFFFFE;}
0342   static short kByteCountVMask() {return 0x4000;}
0343   static uint32 kNewClassTag() {return 0xFFFFFFFF;}
0344 
0345   static int kMapOffset() {return 2;}
0346   static unsigned int kClassMask() {return 0x80000000;}
0347   static uint32 kByteCountMask() {return 0x40000000;}
0348 
0349   bool write_class(const std::string& a_cls){
0350 
0351     std::map<std::string,uint32>::const_iterator it = m_clss.find(a_cls);
0352     if(it!=m_clss.end()) {
0353       uint32 clIdx = (*it).second;
0354 
0355       unsigned int offset = (unsigned int)(m_pos-m_buffer);
0356 
0357       // save index of already stored class
0358       if(!write(uint32(clIdx|kClassMask()))) return false;
0359 
0360       m_cls_mapped.push_back(std::pair<uint32,uint32>(offset,clIdx));
0361 
0362     } else {
0363 
0364       unsigned int offset = (unsigned int)(m_pos-m_buffer);
0365       if(!write(kNewClassTag())) return false;
0366       if(!write_cstring(a_cls.c_str())) return false;
0367       m_clss[a_cls] = offset + kMapOffset();
0368 
0369     }
0370     return true;
0371   }
0372 
0373   bool set_byte_count_obj(uint32 a_pos){
0374     uint32 cnt = (uint32)(m_pos-m_buffer) - a_pos - sizeof(unsigned int);
0375     if(cnt>=kMaxMapCount()) {
0376       m_out << "tools::wroot::buffer::set_byte_count_obj :"
0377             << " bytecount too large (more than "
0378             << kMaxMapCount() << ")."
0379             << std::endl;
0380       return false;
0381     }
0382     char* opos = m_pos;
0383     m_pos = (char*)(m_buffer+a_pos);
0384     if(!m_wb.write(uint32(cnt|kByteCountMask()))) {m_pos = opos;return false;}
0385     m_pos = opos;
0386     return true;
0387   }
0388 
0389 protected:
0390   std::ostream& m_out;
0391   bool m_byte_swap;
0392   uint32 m_size;
0393   char* m_buffer;
0394   char* m_max;
0395   char* m_pos;
0396   wbuf m_wb;
0397 
0398   std::map<ibo*,uint32> m_objs;
0399   std::vector< std::pair<uint32,uint32> > m_obj_mapped;
0400 
0401   std::map<std::string,uint32> m_clss;
0402   std::vector< std::pair<uint32,uint32> > m_cls_mapped;
0403 };
0404 
0405 }}
0406 
0407 #endif