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