Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/wroot/buffer

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  2 // See the file tools.license for terms.
  3 
  4 #ifndef tools_wroot_buffer
  5 #define tools_wroot_buffer
  6 
  7 // class used for serializing objects.
  8 
  9 #include "wbuf"
 10 #include "ibo"
 11 
 12 #include "../realloc"
 13 #include "../mnmx"
 14 #include "../forit"
 15 
 16 #ifdef TOOLS_MEM
 17 #include "../mem"
 18 #endif
 19 
 20 #include <string>
 21 #include <vector>
 22 #include <ostream>
 23 #include <map>
 24 
 25 namespace tools {
 26 namespace wroot {
 27 
 28 class buffer {
 29   static const std::string& s_class() {
 30     static const std::string s_v("tools::wroot::buffer");
 31     return s_v;
 32   }
 33 public:
 34   buffer(std::ostream& a_out,bool a_byte_swap,uint32 a_size) // we expect a not zero value for a_size.
 35   :m_out(a_out)
 36   ,m_byte_swap(a_byte_swap)
 37   ,m_size(0)
 38   ,m_buffer(0)
 39   ,m_max(0)
 40   ,m_pos(0)
 41   ,m_wb(a_out,a_byte_swap,0,m_pos) //it holds a ref on m_pos.
 42   {
 43 #ifdef TOOLS_MEM
 44     mem::increment(s_class().c_str());
 45 #endif
 46     m_size = a_size;
 47     m_buffer = new char[m_size];
 48     //if(!m_buffer) {}
 49     m_max = m_buffer+m_size;
 50     m_pos = m_buffer;
 51     m_wb.set_eob(m_max);
 52   }
 53 
 54   virtual ~buffer(){
 55     m_objs.clear();
 56     m_obj_mapped.clear();
 57 
 58     m_clss.clear();
 59     m_cls_mapped.clear();
 60 
 61     delete [] m_buffer;
 62 #ifdef TOOLS_MEM
 63     mem::decrement(s_class().c_str());
 64 #endif
 65   }
 66 protected:
 67   buffer(const buffer& a_from)
 68   :m_out(a_from.m_out)
 69   ,m_byte_swap(a_from.m_byte_swap)
 70   ,m_size(0)
 71   ,m_buffer(0)
 72   ,m_max(0)
 73   ,m_pos(0)
 74   ,m_wb(a_from.m_out,a_from.m_byte_swap,0,m_pos)
 75   {
 76 #ifdef TOOLS_MEM
 77     mem::increment(s_class().c_str());
 78 #endif
 79   }
 80   buffer& operator=(const buffer&){return *this;}
 81 public:
 82   bool byte_swap() const {return m_byte_swap;}
 83   std::ostream& out() const {return m_out;}
 84 
 85   //void set_offset(unsigned int a_off) {m_pos = m_buffer+a_off;}
 86 
 87   char* buf() {return m_buffer;}
 88   const char* buf() const {return m_buffer;}
 89   uint32 length() const {return uint32(m_pos-m_buffer);}
 90   uint32 size() const {return m_size;}
 91 
 92   char*& pos() {return m_pos;}          //used in basket.
 93   char* max_pos() const {return m_max;} //used in basket.
 94 
 95 public:
 96   template <class T>
 97   bool write(T x){
 98     if(m_pos+sizeof(T)>m_max) {
 99       if(!expand2(m_size+sizeof(T))) return false;
100     }
101     return m_wb.write(x);
102   }
103 
104   bool write(bool x) {return write<unsigned char>(x?1:0);}
105 
106   bool write(const std::string& x) {
107     uint32 sz = (uint32)(x.size() + sizeof(int) + 1);
108     if((m_pos+sz)>m_max) {
109       if(!expand2(m_size+sz)) return false;
110     }
111     return m_wb.write(x);
112   }
113 
114   bool write_fast_array(const char* a_a,uint32 a_n) {
115     if(!a_n) return true;
116     uint32 l = a_n * sizeof(char);
117     if((m_pos+l)>m_max) {
118       if(!expand2(m_size+l)) return false;
119     }
120     ::memcpy(m_pos,a_a,l);
121     m_pos += l;
122     return true;
123   }
124 
125   bool write_cstring(const char* a_s) {return write_fast_array(a_s,(uint32(::strlen(a_s))+1)*sizeof(char));}
126 
127   template <class T>
128   bool write_fast_array(const T* a_a,uint32 a_n) {
129     if(!a_n) return true;
130     uint32 l = a_n * sizeof(T);
131     if((m_pos+l)>m_max) {
132       if(!expand2(m_size+l)) return false;
133     }
134     return m_wb.write<T>(a_a,a_n);
135   }
136 
137   template <class T>
138   bool write_fast_array(const std::vector<T>& a_v) {
139     if(a_v.empty()) return true;
140     uint32 l = uint32(a_v.size() * sizeof(T));
141     if((m_pos+l)>m_max) {
142       if(!expand2(m_size+l)) return false;
143     }
144     return m_wb.write<T>(a_v);
145   }
146 
147   template <class T>
148   bool write_array(const T* a_a,uint32 a_n) {
149     if(!write(a_n)) return false;
150     return write_fast_array(a_a,a_n);
151   }
152 
153   template <class T>
154   bool write_array(const std::vector<T>& a_v) {
155     if(!write((uint32)a_v.size())) return false;
156     return write_fast_array(a_v);
157   }
158 
159   template <class T>
160   bool write_array2(const std::vector< std::vector<T> >& a_v) {
161     if(!write((uint32)a_v.size())) return false;
162     for(unsigned int index=0;index<a_v.size();index++) {
163       if(!write_array(a_v[index])) return false;
164     }
165     return true;
166   }
167 
168 public:
169   bool write_version(short a_version){
170     if(a_version>kMaxVersion()) {
171       m_out << "tools::wroot::buffer::write_version :"
172             << " version number " << a_version
173             << " cannot be larger than " << kMaxVersion() << "."
174             << std::endl;
175       return false;
176     }
177     return write(a_version);
178   }
179   bool write_version(short a_version,uint32& a_pos){
180     // reserve space for leading byte count
181     a_pos = (uint32)(m_pos-m_buffer);
182 
183     //NOTE : the below test is lacking in CERN-ROOT !
184     if((m_pos+sizeof(unsigned int))>m_max) {
185       if(!expand2(m_size+sizeof(unsigned int))) return false;
186     }
187     m_pos += sizeof(unsigned int);
188 
189     if(a_version>kMaxVersion()) {
190       m_out << "tools::wroot::buffer::write_version :"
191             << " version number " << a_version
192             << " cannot be larger than " << kMaxVersion() << "."
193             << std::endl;
194       return false;
195     }
196     return write(a_version);
197   }
198 
199   bool set_byte_count(uint32 a_pos){
200     uint32 cnt = (uint32)(m_pos-m_buffer) - a_pos - sizeof(unsigned int);
201     if(cnt>=kMaxMapCount()) {
202       m_out << "tools::wroot::buffer::set_byte_count :"
203             << " bytecount too large (more than "
204             << kMaxMapCount() << ")."
205             << std::endl;
206       return false;
207     }
208 
209     union {
210       uint32 cnt;
211       short vers[2];
212     } v;
213     v.cnt = cnt;
214 
215     char* opos = m_pos;
216     m_pos = (char*)(m_buffer+a_pos);
217     if(m_byte_swap) {
218       if(!m_wb.write(short(v.vers[1]|kByteCountVMask())))
219         {m_pos = opos;return false;}
220       if(!m_wb.write(v.vers[0])) {m_pos = opos;return false;}
221     } else {
222       if(!m_wb.write(short(v.vers[0]|kByteCountVMask())))
223         {m_pos = opos;return false;}
224       if(!m_wb.write(v.vers[1])) {m_pos = opos;return false;}
225     }
226     m_pos = opos;
227 
228     return true;
229   }
230 
231   bool write_object(const ibo& a_obj){
232     //GB : if adding a write map logic, think to have a displace_mapped()
233     //     in basket::write_on_file().
234 
235     std::map<ibo*,uint32>::const_iterator it = m_objs.find((ibo*)&a_obj);
236     if(it!=m_objs.end()) {
237 
238       uint32 objIdx = (*it).second;
239 
240       unsigned int offset = (unsigned int)(m_pos-m_buffer);
241 
242       // save index of already stored object
243       if(!write(objIdx)) return false;
244 
245       m_obj_mapped.push_back(std::pair<uint32,uint32>(offset,objIdx));
246 
247     } else {
248 
249       // reserve space for leading byte count
250       uint32 cntpos = (unsigned int)(m_pos-m_buffer);
251 
252       //NOTE : the below test is lacking in CERN-ROOT !
253       if((m_pos+sizeof(unsigned int))>m_max) {
254         if(!expand2(m_size+sizeof(unsigned int))) return false;
255       }
256       m_pos += sizeof(unsigned int);
257 
258       // write class of object first
259       if(!write_class(a_obj.store_cls())) return false;
260 
261       // add to map before writing rest of object (to handle self reference)
262       // (+kMapOffset so it's != kNullTag)
263       m_objs[(ibo*)&a_obj] = cntpos + kMapOffset();
264 
265       // let the object write itself :
266       if(!a_obj.stream(*this)) return false;
267 
268       // write byte count
269       if(!set_byte_count_obj(cntpos)) return false;
270     }
271     return true;
272   }
273 
274   bool expand2(uint32 a_new_size) {return expand(mx<uint32>(2*m_size,a_new_size));} //CERN-ROOT logic.
275 
276   bool expand(uint32 a_new_size) {
277     diff_pointer_t len = m_pos-m_buffer;
278     if(!realloc<char>(m_buffer,a_new_size,m_size)) {
279       m_out << "tools::wroot::buffer::expand :"
280             << " can't realloc " << a_new_size << " bytes."
281             << std::endl;
282       m_size = 0;
283       m_max = 0;
284       m_pos = 0;
285       m_wb.set_eob(m_max);
286       return false;
287     }
288     m_size = a_new_size;
289     m_max = m_buffer + m_size;
290     m_pos = m_buffer + len;
291     m_wb.set_eob(m_max);
292     return true;
293   }
294 
295   size_t to_displace() const {return m_cls_mapped.size()+m_obj_mapped.size();}
296 
297   bool displace_mapped(unsigned int a_num){
298     char* opos = m_pos;
299 
300     //m_out << "tools::wroot::buffer::displace_mapped :"
301     //      << " cls num " << m_cls_mapped.size()
302     //      << std::endl;
303 
304     typedef std::pair<uint32,uint32> offset_id;
305 
306    {tools_vforcit(offset_id,m_cls_mapped,it) {
307       unsigned int offset = (*it).first;
308       unsigned int id = (*it).second;
309       //m_out << "displace " << offset << " " << id << std::endl;
310       m_pos = m_buffer+offset;
311       unsigned int clIdx = id+a_num;
312       if(!write(uint32(clIdx|kClassMask()))) {m_pos = opos;return false;}
313     }}
314 
315     //m_out << "tools::wroot::buffer::displace_mapped :"
316     //      << " obj num " << m_obj_mapped.size()
317     //      << std::endl;
318 
319    {tools_vforcit(offset_id,m_obj_mapped,it) {
320       uint32 offset = (*it).first;
321       uint32 id = (*it).second;
322       //m_out << "displace at " << offset
323       //      << " the obj pos " << id
324       //      << " by " << a_num
325       //      << std::endl;
326       m_pos = m_buffer+offset;
327       unsigned int objIdx = id+a_num;
328       if(!write(objIdx)) {m_pos = opos;return false;}
329     }}
330 
331     m_pos = opos;
332     return true;
333   }
334 
335   void reset_objs_map() {
336     m_objs.clear();
337     //m_clss.clear();
338   }
339 protected:
340   static short kMaxVersion() {return 0x3FFF;}
341   static uint32 kMaxMapCount() {return 0x3FFFFFFE;}
342   static short kByteCountVMask() {return 0x4000;}
343   static uint32 kNewClassTag() {return 0xFFFFFFFF;}
344 
345   static int kMapOffset() {return 2;}
346   static unsigned int kClassMask() {return 0x80000000;}
347   static uint32 kByteCountMask() {return 0x40000000;}
348 
349   bool write_class(const std::string& a_cls){
350 
351     std::map<std::string,uint32>::const_iterator it = m_clss.find(a_cls);
352     if(it!=m_clss.end()) {
353       uint32 clIdx = (*it).second;
354 
355       unsigned int offset = (unsigned int)(m_pos-m_buffer);
356 
357       // save index of already stored class
358       if(!write(uint32(clIdx|kClassMask()))) return false;
359 
360       m_cls_mapped.push_back(std::pair<uint32,uint32>(offset,clIdx));
361 
362     } else {
363 
364       unsigned int offset = (unsigned int)(m_pos-m_buffer);
365       if(!write(kNewClassTag())) return false;
366       if(!write_cstring(a_cls.c_str())) return false;
367       m_clss[a_cls] = offset + kMapOffset();
368 
369     }
370     return true;
371   }
372 
373   bool set_byte_count_obj(uint32 a_pos){
374     uint32 cnt = (uint32)(m_pos-m_buffer) - a_pos - sizeof(unsigned int);
375     if(cnt>=kMaxMapCount()) {
376       m_out << "tools::wroot::buffer::set_byte_count_obj :"
377             << " bytecount too large (more than "
378             << kMaxMapCount() << ")."
379             << std::endl;
380       return false;
381     }
382     char* opos = m_pos;
383     m_pos = (char*)(m_buffer+a_pos);
384     if(!m_wb.write(uint32(cnt|kByteCountMask()))) {m_pos = opos;return false;}
385     m_pos = opos;
386     return true;
387   }
388 
389 protected:
390   std::ostream& m_out;
391   bool m_byte_swap;
392   uint32 m_size;
393   char* m_buffer;
394   char* m_max;
395   char* m_pos;
396   wbuf m_wb;
397 
398   std::map<ibo*,uint32> m_objs;
399   std::vector< std::pair<uint32,uint32> > m_obj_mapped;
400 
401   std::map<std::string,uint32> m_clss;
402   std::vector< std::pair<uint32,uint32> > m_cls_mapped;
403 };
404 
405 }}
406 
407 #endif