g4tools  5.4.0
buffer
Go to the documentation of this file.
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) {}
50  m_pos = m_buffer;
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) {
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 
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;
393  char* m_buffer;
394  char* m_max;
395  char* m_pos;
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
tools::wroot::buffer::write_version
bool write_version(short a_version, uint32 &a_pos)
Definition: buffer:179
tools::wroot::ibo::store_cls
virtual const std::string & store_cls() const =0
tools::wroot::buffer::reset_objs_map
void reset_objs_map()
Definition: buffer:335
tools::wroot::buffer::max_pos
char * max_pos() const
Definition: buffer:93
tools::wroot::buffer::byte_swap
bool byte_swap() const
Definition: buffer:82
tools::wroot::buffer::expand
bool expand(uint32 a_new_size)
Definition: buffer:276
tools::wroot::buffer::set_byte_count_obj
bool set_byte_count_obj(uint32 a_pos)
Definition: buffer:373
tools::wroot::buffer::write_array
bool write_array(const std::vector< T > a_v)
Definition: buffer:154
tools::wroot::buffer::buf
const char * buf() const
Definition: buffer:88
tools::wroot::buffer::length
uint32 length() const
Definition: buffer:89
tools::wroot::buffer::size
uint32 size() const
Definition: buffer:90
tools::wroot::buffer::kMapOffset
static int kMapOffset()
Definition: buffer:345
tools::wroot::buffer::kByteCountVMask
static short kByteCountVMask()
Definition: buffer:342
wbuf
tools::wroot::buffer::operator=
buffer & operator=(const buffer &)
Definition: buffer:80
tools::wroot::buffer::write_cstring
bool write_cstring(const char *a_s)
Definition: buffer:125
tools::wroot::buffer::kNewClassTag
static uint32 kNewClassTag()
Definition: buffer:343
tools::wroot::buffer::write_fast_array
bool write_fast_array(const std::vector< T > &a_v)
Definition: buffer:138
tools::wroot::ibo
Definition: ibo:17
tools::wroot::ibo::stream
virtual bool stream(buffer &) const =0
tools::wroot::buffer::write_object
bool write_object(const ibo &a_obj)
Definition: buffer:231
tools::wroot::buffer::~buffer
virtual ~buffer()
Definition: buffer:54
tools::wroot::wbuf::set_eob
void set_eob(const char *a_eob)
Definition: wbuf:119
tools::wroot::buffer::m_pos
char * m_pos
Definition: buffer:395
tools::wroot::buffer::set_byte_count
bool set_byte_count(uint32 a_pos)
Definition: buffer:199
tools::wroot::buffer::m_cls_mapped
std::vector< std::pair< uint32, uint32 > > m_cls_mapped
Definition: buffer:402
tools::wroot::wbuf
Definition: wbuf:22
tools::wroot::buffer::write
bool write(const std::string &x)
Definition: buffer:106
tools::wroot::buffer::buf
char * buf()
Definition: buffer:87
tools::wroot::buffer::displace_mapped
bool displace_mapped(unsigned int a_num)
Definition: buffer:297
tools::wroot::buffer::buffer
buffer(const buffer &a_from)
Definition: buffer:67
tools::wroot::buffer::m_byte_swap
bool m_byte_swap
Definition: buffer:391
tools::wroot::buffer::expand2
bool expand2(uint32 a_new_size)
Definition: buffer:274
tools::wroot::buffer::m_obj_mapped
std::vector< std::pair< uint32, uint32 > > m_obj_mapped
Definition: buffer:399
tools::wroot::buffer::write_version
bool write_version(short a_version)
Definition: buffer:169
tools::wroot::buffer::write_array
bool write_array(const T *a_a, uint32 a_n)
Definition: buffer:148
tools::wroot::buffer::kMaxMapCount
static uint32 kMaxMapCount()
Definition: buffer:341
tools::wroot::buffer::write
bool write(T x)
Definition: buffer:97
tools::wroot::buffer::out
std::ostream & out() const
Definition: buffer:83
tools::wroot::buffer::write_fast_array
bool write_fast_array(const char *a_a, uint32 a_n)
Definition: buffer:114
tools::diff_pointer_t
unsigned long diff_pointer_t
Definition: typedefs:76
tools::wroot::buffer::m_objs
std::map< ibo *, uint32 > m_objs
Definition: buffer:398
tools::wroot::buffer::kByteCountMask
static uint32 kByteCountMask()
Definition: buffer:347
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
ibo
tools::wroot::buffer
Definition: buffer:28
tools::wroot::buffer::m_out
std::ostream & m_out
Definition: buffer:390
tools::wroot::buffer::write_class
bool write_class(const std::string &a_cls)
Definition: buffer:349
tools::wroot::buffer::write
bool write(bool x)
Definition: buffer:104
tools::wroot::buffer::kMaxVersion
static short kMaxVersion()
Definition: buffer:340
tools::wroot::buffer::m_clss
std::map< std::string, uint32 > m_clss
Definition: buffer:401
tools::wroot::buffer::m_wb
wbuf m_wb
Definition: buffer:396
tools::wroot::buffer::kClassMask
static unsigned int kClassMask()
Definition: buffer:346
tools::wroot::buffer::buffer
buffer(std::ostream &a_out, bool a_byte_swap, uint32 a_size)
Definition: buffer:34
tools::wroot::buffer::pos
char *& pos()
Definition: buffer:92
tools::wroot::buffer::m_size
uint32 m_size
Definition: buffer:392
tools::wroot::buffer::to_displace
size_t to_displace() const
Definition: buffer:295
tools_vforcit
#define tools_vforcit(a__T, a__v, a__it)
Definition: forit:7
tools::wroot::buffer::write_fast_array
bool write_fast_array(const T *a_a, uint32 a_n)
Definition: buffer:128
tools::wroot::buffer::write_array2
bool write_array2(const std::vector< std::vector< T > > a_v)
Definition: buffer:160
tools::wroot::buffer::m_max
char * m_max
Definition: buffer:394
tools::uint32
unsigned int uint32
Definition: typedefs:71
tools::wroot::buffer::m_buffer
char * m_buffer
Definition: buffer:393
tools::wroot::wbuf::write
bool write(unsigned char a_x)
Definition: wbuf:134