Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/rroot/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_rroot_buffer
  5 #define tools_rroot_buffer
  6 
  7 #include "rbuf"
  8 #include "ifac"
  9 #include "iro"
 10 #include "../sout"
 11 #include "../mapmanip"
 12 #ifdef TOOLS_MEM
 13 #include "../mem"
 14 #endif
 15 
 16 #include <string>
 17 #include <vector>
 18 #include <ostream>
 19 #include <utility>
 20 
 21 // in TOOLS_STL, we don't have (yet) a performant map.
 22 
 23 #ifdef tools_stl_vector
 24 #define TOOLS_RROOT_OBJ_MAP_HASH_TABLE
 25 //#define TOOLS_RROOT_OBJ_MAP_OMAP
 26 #else
 27 #define TOOLS_RROOT_OBJ_MAP_STD_MAP
 28 #endif
 29 
 30 #ifdef TOOLS_RROOT_OBJ_MAP_STD_MAP
 31 #include <map>
 32 #endif
 33 #ifdef TOOLS_RROOT_OBJ_MAP_OMAP
 34 #include "../omap"
 35 #endif
 36 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
 37 #include "../hash_table"
 38 #include "../hash"
 39 #endif
 40 
 41 namespace tools {
 42 namespace rroot {
 43 
 44 class buffer : public rbuf {
 45   typedef rbuf parent;
 46 
 47   static const std::string& s_class() {
 48     static const std::string s_v("tools::rroot::buffer");
 49     return s_v;
 50   }
 51 
 52 #ifdef TOOLS_RROOT_OBJ_MAP_STD_MAP
 53   typedef std::map<uint32,iro*> obj_map;
 54 #endif
 55 #ifdef TOOLS_RROOT_OBJ_MAP_OMAP
 56   typedef omap<uint32,iro*> obj_map;
 57 #endif
 58 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
 59   class obj_map : public hash_table<uint32,iro*> {
 60     typedef hash_table<uint32,iro*> parent;
 61   protected:
 62     virtual unsigned int hash(const uint32& a_key) {
 63       return hash(&a_key,sizeof(uint32));
 64     }
 65     virtual bool cmp(const uint32& a_key1,const uint32& a_key2) {
 66       return a_key1==a_key2?true:false;
 67     }
 68   public:
 69     obj_map():parent(){}
 70     virtual ~obj_map(){}
 71   private:
 72     obj_map(const obj_map& a_from):parent(a_from){}
 73     obj_map& operator=(const obj_map& a_from){
 74       parent::operator=(a_from);
 75       return *this;
 76     }
 77   };
 78 #endif
 79 
 80 public:
 81   buffer(std::ostream& a_out,bool a_byte_swap,uint32 a_size,char* a_buffer,uint32 a_klen,bool a_verbose)
 82   :parent(a_out,a_byte_swap,a_buffer+a_size,m_pos)
 83   ,m_byte_swap(a_byte_swap)
 84   ,m_verbose(a_verbose)
 85   //,m_verbose(true)
 86   ,m_size(a_size)     //expect a not zero size.
 87   ,m_buffer(a_buffer) //don't get ownership.
 88   ,m_pos(a_buffer)
 89   ,m_klen(a_klen) //to compute refs (used in read_class, read_object)
 90 //,m_map_objs(false)
 91   ,m_map_objs(true)
 92   {
 93 #ifdef TOOLS_MEM
 94     mem::increment(s_class().c_str());
 95 #endif
 96   }
 97   virtual ~buffer(){
 98     m_objs.clear();
 99 #ifdef TOOLS_MEM
100     mem::decrement(s_class().c_str());
101 #endif
102   }
103 protected:
104   buffer(const buffer& a_from)
105   :parent(a_from.m_out,a_from.m_byte_swap,0,m_pos)
106   ,m_byte_swap(a_from.m_byte_swap)
107   ,m_map_objs(a_from.m_map_objs)
108   {
109 #ifdef TOOLS_MEM
110     mem::increment(s_class().c_str());
111 #endif
112   }
113   buffer& operator=(const buffer&){return *this;}
114 public:
115   bool byte_swap() const {return m_byte_swap;}
116   bool verbose() const {return m_verbose;}
117 
118   void set_offset(unsigned int a_off) {m_pos = m_buffer+a_off;}
119 
120   //char* buffer() const {return m_buffer;}
121   uint32 length() const {return uint32(m_pos-m_buffer);}
122   uint32 size() const {return m_size;}
123 
124   void set_map_objs(bool a_value) {m_map_objs = a_value;}
125   bool map_objs() const {return m_map_objs;}
126 protected:
127   // on first_int :
128   static uint32 kNullTag() {return 0;}
129   static uint32 kByteCountMask() {return 0x40000000;}
130   // on tag :
131   static uint32 kNewClassTag() {return 0xFFFFFFFF;}
132   static uint32 kClassMask() {return 0x80000000;  }
133   static uint32 kMapOffset() {return 2;}
134   static short kByteCountVMask() {return 0x4000;}
135 
136   bool read_class_tag(std::string& a_class) {
137     a_class.clear();
138 
139     uint32 tag;
140     if(!parent::read(tag)) return false;
141 
142     if(tag==kNewClassTag()) {
143       char _s[80];
144       if(!read_string(_s, 80)) {
145         m_out << "tools::rroot::read_class_tag :"
146               << " read string." << std::endl;
147         return false;
148       }
149       //m_out << "tools::rroot::read_class_tag :"
150       //      << " tag kNewClassTag"
151       //      << " class " << _s
152       //      << std::endl;
153       a_class = _s;
154       return true;
155 
156     } else if(tag & kClassMask()) {
157       //m_out << "tools::rroot::read_class_tag :"
158       //      << " tag & kClassMask"
159       //      << " ref " << (uint32)(tag & ~kClassMask)
160       //      << " recurse..."
161       //      << std::endl;
162 
163       unsigned int cl_offset = (tag & ~kClassMask());
164       cl_offset -= kMapOffset();
165       cl_offset -= m_klen;
166       char* old_pos = m_pos;
167       m_pos = m_buffer + cl_offset;
168       //std::string scls;
169       //uint32 ref;
170       if(!read_class_tag(a_class)) return false;
171       m_pos = old_pos;
172 
173       return true;
174 
175     } else {
176 
177       std::ios::fmtflags old_flags = m_out.flags();
178       m_out << "tools::rroot::read_class_tag :"
179             << " tag unknown case ! "
180             << tag << " hex " << std::hex << tag
181             << std::endl;
182       m_out.flags(old_flags);
183 
184       return false;
185     }
186   }
187 
188   bool read_class(std::string& a_class,uint32& a_bcnt,bool& a_is_ref){
189     //m_verbose = true;
190     a_class.clear();
191     a_bcnt = 0;
192     a_is_ref = false;
193 
194     //uint32 fVersion = 0;       //Buffer format version
195 
196     // read byte count and/or tag (older files don't have byte count)
197     uint32 first_int = 0;
198     if(!parent::read(first_int)) return false;
199 
200     if(m_verbose) {
201       std::ios::fmtflags old_flags = m_out.flags();
202       m_out << "tools::rroot::read_class :"
203             << " first_int " << std::hex << first_int
204             << std::endl;
205       m_out.flags(old_flags);
206     }
207 
208     if(first_int==kNullTag()) { //GB
209       if(m_verbose) {
210         m_out << "tools::rroot::read_class :"
211               << " first_int is kNullTag."
212               << std::endl;
213       }
214       a_bcnt = 0;
215       return true;
216 
217   //} else if(first_int==kNewClassTag()) { // class desc follows.
218     } else if(first_int & kByteCountMask()) {
219       // at write :
220       //   skip int to store bcnt.
221       // + write class
222       //     if(!write((clIdx | Rio_kClassMask))) return false;
223       //   or
224       //     if(!write(Rio_kNewClassTag)) return false;
225       // + write object
226       // + set byte cnt (cnt|kByteCountMask()) at skipped int.
227 
228       if(m_verbose) {
229         m_out << "tools::rroot::read_class :"
230               << " first_int & kByteCountMask."
231               << std::endl;
232       }
233 
234       uint32 bef_tag = uint32(m_pos-m_buffer);
235       //fVersion = 1;
236 
237       std::string scls;
238       if(!read_class_tag(scls)) return false;
239       if(scls.empty()) {
240         m_out << "tools::rroot::buffer::read_class :"
241               << " read_class_tag did not find a class name."
242               << std::endl;
243         return false;
244       }
245 
246       a_class = std::move(scls);
247       a_bcnt = (first_int & ~kByteCountMask());
248 
249       if(m_verbose) {
250         m_out << "tools::rroot::read_class :"
251               << " kNewClassTag : read class name " << sout(a_class)
252               << " a_bcnt " << a_bcnt
253               << " bef_tag " << bef_tag
254               << "." << std::endl;
255       }
256 
257       return true;
258 
259     } else {
260       if(m_verbose) {
261         std::ios::fmtflags old_flags = m_out.flags();
262         m_out << "tools::rroot::read_class :"
263               << " first_int " << std::hex << first_int
264                << ". first_int is position toward object."
265                << std::endl;
266         m_out.flags(old_flags);
267       }
268       a_bcnt = first_int; //pos toward object.
269       a_is_ref = true;
270       a_class.clear();
271       return true;
272     }
273 
274     return false;
275   }
276 public:
277   void remove_in_map(iro* a_obj) {
278 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
279     m_out << "tools::rroot::remove_in_map : dummy." << std::endl;
280 #else
281     find_and_remove_value(m_objs,a_obj);
282 #endif
283   }
284   bool read_object(ifac& a_fac,const ifac::args& a_args,iro*& a_obj,bool& a_created){
285     a_obj = 0;
286     a_created = false;
287 
288     //m_out << "debug : tools::rroot::buffer::read_object : begin :" << std::endl;
289 
290     // before reading object save start position
291     uint32 startpos = (uint32)(m_pos-m_buffer);
292 
293     uint32 bcnt;
294     std::string sclass;
295     bool is_ref;
296     if(!read_class(sclass,bcnt,is_ref)) {
297       m_out << "tools::rroot::buffer::read_object :"
298             << " can't read class." << std::endl;
299       return false;
300     }
301     //::printf("debug : %d\n",length()-startpos);
302 
303     if(m_verbose) {
304       m_out << "tools::rroot::buffer::read_object :"
305             << " class " << sout(sclass) << ", is_ref " << is_ref
306             << ", bcnt " << bcnt
307             << std::endl;
308     }
309 
310     if(is_ref) { //bcnt is the position toward an object or an object ref.
311       //m_out << "debug : tools::rroot::buffer::read_object : is_ref : bcnt " << bcnt << std::endl;
312 
313       unsigned int obj_offset = bcnt;
314       obj_offset -= kMapOffset();
315       obj_offset -= m_klen;
316 
317       if(!m_map_objs) {
318         m_out << "tools::rroot::buffer::read_object : warning :"
319               << " class " << sout(sclass) << ", is_ref but map objs is not enabled on this buffer."
320               << std::endl;
321       }
322 
323       if(m_map_objs) {
324 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
325         if(m_objs.find(obj_offset,a_obj)) {
326           //m_out << "debug : tools::rroot::buffer::read_object : found object in map." << bcnt << std::endl;
327           return true;
328         }
329 #else
330         obj_map::const_iterator it = m_objs.find(obj_offset);
331         if(it!=m_objs.end()) {
332           a_obj = (*it).second;
333           //::printf("debug : find : %d %lu\n",obj_offset,a_obj);
334           //stay at current m_pos ?
335           return true;
336         }
337 #endif
338       }
339 
340      {char* old_pos = m_pos;
341 
342       m_pos = m_buffer + obj_offset;
343 
344       uint32 first_int;
345       if(!parent::read(first_int)) {
346         m_out << "tools::rroot::buffer::read_object : parent::read(first_int) failed." << std::endl;
347         return false;
348       }
349       if(first_int & kByteCountMask()) {
350         std::string scls;
351         if(!read_class_tag(scls)) {
352           m_out << "tools::rroot::buffer::read_object : read_class_tag() failed." << std::endl;
353           return false;
354   }
355         if(scls.empty()) {
356           m_out << "tools::rroot::buffer::read_object :"
357                 << " read_class_tag did not find a class name."
358                 << std::endl;
359           return false;
360         }
361 
362         //m_out << "tools::rroot::buffer::read_object :"
363         //      << " is_ref : class " << sout(scls)
364         //      << std::endl;
365 
366         iro* obj = a_fac.create(scls,a_args);
367         if(!obj) {
368           m_out << "tools::rroot::buffer::read_object : is_ref : creation of object"
369                 << " of class " << sout(sclass) << " failed." << std::endl;
370     return false;
371   }
372 
373         if(m_map_objs) {
374           //must be done before stream()
375 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
376           if(!m_objs.insert(obj_offset,obj)) {
377             m_out << "tools::rroot::buffer::read_object :"
378                   << " map insert failed."
379                   << std::endl;
380           }
381 #else
382           m_objs[obj_offset] = obj;
383 #endif
384         }
385 
386         if(!obj->stream(*this)) {
387           m_out << "tools::rroot::buffer::read_object :"
388                 << " is_ref : streamed failed for class " << sout(scls)
389                 << std::endl;
390           //restore a good buffer position :
391           //m_pos = m_buffer+startpos+sizeof(unsigned int);
392           delete obj;
393           return false;
394         }
395 
396         //m_out << "tools::rroot::buffer::read_object :"
397         //      << " is_ref : streamed ok for class " << sout(scls)
398         //      << std::endl;
399 
400         a_obj = obj;
401         a_created = true;
402 
403       } else {
404         m_out << "tools::rroot::buffer::read_object :"
405               << " is_ref : zzz"
406               << std::endl;
407       }
408 
409       m_pos = old_pos;}
410 
411       // in principle at this point m_pos should be
412       //   m_buffer+startpos+sizeof(unsigned int)
413       // but enforce it anyway :
414       m_pos = m_buffer+startpos+sizeof(unsigned int);
415       //check_byte_count(startpos,0,sclass) would always be ok.
416 
417       //a_obj = ???
418 
419     } else {
420       if(sclass.empty()) {
421         //m_out << "debug : tools::rroot::buffer::read_object : found empty class name." << std::endl;
422 
423         m_pos = m_buffer+startpos+bcnt+sizeof(unsigned int);
424 
425       } else {
426         //m_out << "debug : tools::rroot::buffer::read_object : not a ref, create object." << std::endl;
427 
428         // Being not a ref, it must NOT be in the map.
429         // We gain a lot by not doing the below find.
430 /*
431         if(m_map_objs) {
432 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
433           if(m_objs.find(startpos,a_obj)) return true;
434 #else
435           obj_map::const_iterator it = m_objs.find(startpos);
436           if(it!=m_objs.end()) {
437             a_obj = (*it).second;
438             ::printf("debug : find xxx : %d %lu\n",startpos,a_obj);
439             //stay at current m_pos ?
440             return true;
441           }
442 #endif
443         }
444 */
445 
446         iro* obj = a_fac.create(sclass,a_args);
447         if(!obj) {
448           m_out << "tools::rroot::buffer::read_object : creation of object"
449                 << " of class " << sout(sclass) << " failed." << std::endl;
450           return false;
451         }
452         //m_out << "debug : tools::rroot::buffer::read_object : object created." << std::endl;
453 
454         if(m_map_objs) {
455           //must be done before stream()
456 #ifdef TOOLS_RROOT_OBJ_MAP_HASH_TABLE
457           if(!m_objs.insert(startpos,obj)) {
458             m_out << "tools::rroot::buffer::read_object :"
459                   << " map insert failed."
460                   << std::endl;
461           }
462 #else
463           m_objs[startpos] = obj;
464 #endif
465         }
466 
467         //::printf("debug : map : %d %lu\n",startpos,obj);
468 
469         //NOTE : if class ref, "up there"-startpos = 8.
470         if(!obj->stream(*this)) {
471           m_out << "tools::rroot::buffer::read_object : object.stream() failed"
472                 << " for object of class " << sout(sclass) << "." << std::endl;
473           //restore a good buffer position :
474           //m_pos = m_buffer+startpos+bcnt+sizeof(unsigned int);
475           delete obj;
476           return false;
477         }
478 
479         //NOTE : if obj stream ok, the below line is not needed.
480         //m_pos = m_buffer+startpos+bcnt+sizeof(unsigned int);
481 
482         if(!check_byte_count(startpos,bcnt,sclass)) {
483           m_out << "tools::rroot::buffer::read_object :"
484                 << " check_byte_count failed "
485                 << "for object of class "
486                 << sout(sclass) << "." << std::endl;
487           delete obj;
488           return false;
489         }
490 
491         a_obj = obj;
492         a_created = true;
493       }
494 
495     }
496 
497     if(m_verbose) {
498       m_out << "tools::rroot::buffer::read_object : end." << std::endl;
499     }
500 
501     return true;
502   }
503 public:
504   bool read_version(short& a_version){
505     // Read class version from I/O buffer.
506     // Is read a short or three shorts.
507     a_version = 0;
508     short version = 0;
509     // not interested in byte count
510     if(!parent::read(version)) return false;
511 
512     // if this is a byte count, then skip next short and read version
513     if(version & kByteCountVMask()) {
514       if(!parent::read(version)) return false;
515       if(!parent::read(version)) return false;
516     }
517 
518     a_version = version;
519     return true;
520   }
521 
522   bool read_version(short& a_version,uint32& a_start_pos,uint32& a_byte_count){
523     // Read class version from I/O buffer.
524     // Is read one or three shorts.
525     a_version = 0;
526     a_start_pos = 0;
527     a_byte_count = 0;
528 
529     short version = 0;
530 
531     // before reading object save start position
532     uint32 startpos = (uint32)(m_pos-m_buffer);
533 
534     // read byte count (older files don't have byte count)
535     // byte count is packed in two individual shorts, this to be
536     // backward compatible with old files that have at this location
537     // only a single short (i.e. the version)
538     union {
539       unsigned int cnt;
540       short vers[2];
541     } v;
542 
543     if(m_byte_swap) {
544       if(!parent::read(v.vers[1])) return false;
545       if(!parent::read(v.vers[0])) return false;
546     } else {
547       if(!parent::read(v.vers[0])) return false;
548       if(!parent::read(v.vers[1])) return false;
549     }
550 
551     // no bytecount, backup and read version
552     uint32 bcnt = 0;
553     if(v.cnt & kByteCountMask()) {
554       bcnt = (v.cnt & ~kByteCountMask());
555     } else {
556       m_pos -= sizeof(unsigned int);
557     }
558     if(!parent::read(version)) return false;
559     //printf("Reading version=%d at pos=%d, bytecount=%d\n",
560     //version,*startpos,*bcnt);
561 
562     a_version = version;
563     a_start_pos = startpos;
564     a_byte_count = bcnt;
565 
566     return true;
567   }
568 
569   bool check_byte_count(uint32 a_start_pos,uint32 a_byte_count,const std::string& a_store_cls){
570     if(!a_byte_count) return true;
571 
572     size_t len = a_start_pos + a_byte_count + sizeof(unsigned int);
573 
574     size_t diff = size_t(m_pos-m_buffer);
575 
576     if(diff==len) return true;
577 
578     if(diff<len) {
579       m_out << "tools::rroot::buffer::check_byte_count :"
580             << " object of class " << sout(a_store_cls)
581             << " read too few bytes ("
582             << long_out(long(len-diff)) << " missing)."
583             << std::endl;
584     }
585     if(diff>len) {
586       m_out << "tools::rroot::buffer::check_byte_count :"
587             << " object of class " << sout(a_store_cls)
588             << " read too many bytes ("
589             << long_out(long(diff-len)) << " in excess)." << std::endl;
590     }
591 
592     m_out << "tools::rroot::buffer::check_byte_count :"
593           << " " << sout(a_store_cls)
594           << " streamer not in sync with data on file, fix streamer."
595           << std::endl;
596 
597     m_pos = m_buffer+len;
598 
599     return false;
600   }
601 protected:
602   bool read_string(char* a_string,uint32 a_max) {
603     // Read string from I/O buffer. String is read till 0 character is
604     // found or till max-1 characters are read (i.e. string s has max
605     // bytes allocated).
606     int nr = 0;
607     while (nr < int(a_max-1)) {
608       char ch;
609       if(!parent::read(ch)) return false;
610       // stop when 0 read
611       if(ch == 0) break;
612       a_string[nr++] = ch;
613     }
614     a_string[nr] = 0;
615     return true;
616   }
617 protected:
618   // buffer objects cannot be copied or assigned
619   //void checkCount(unsigned int);
620   //unsigned int checkObject(unsigned int,const IClass*,bool = false);
621 protected:
622   bool m_byte_swap;
623   bool m_verbose;
624   uint32 m_size;
625   char* m_buffer;
626   char* m_pos;
627   uint32 m_klen; //GB
628   bool m_map_objs;
629   obj_map m_objs;
630 };
631 
632 inline bool dummy_TXxx_pointer_stream(buffer& a_buffer,ifac& a_fac) {
633   ifac::args args;
634   iro* obj;
635   bool created;
636   bool status = a_buffer.read_object(a_fac,args,obj,created);
637   if(obj) {
638     if(created) {
639       if(a_buffer.map_objs()) a_buffer.remove_in_map(obj);
640       delete obj;
641     }
642   }
643   return status;
644 }
645 
646 template <class T>
647 inline bool pointer_stream(buffer& a_buffer,
648                            ifac& a_fac,ifac::args& a_args,
649                            const std::string& a_T_class,
650                            T*& a_obj,bool& a_created){
651   iro* obj;
652   if(!a_buffer.read_object(a_fac,a_args,obj,a_created)) {
653     a_buffer.out() << "tools::rroot::pointer_stream : read_object failed." << std::endl;
654     a_obj = 0;
655     a_created = false;
656     return false;
657   }
658   if(!obj) {
659     a_obj = 0;
660     a_created = false;
661   } else {
662     a_obj = (T*)obj->cast(a_T_class);
663     if(!a_obj) {
664       a_buffer.out() << "tools::rroot::pointer_stream : "
665                      << " tools::cast to " << a_T_class << " failed."
666                      << ". Object is a " << obj->s_cls() << "."
667                      << std::endl;
668       if(a_created) delete obj;
669       a_created = false;
670       return false;
671     }
672   }
673   return true;
674 }
675 
676 template <class T>
677 inline bool pointer_stream(buffer& a_buffer,
678                            ifac& a_fac,ifac::args& a_args,
679                            cid a_T_class,
680                            T*& a_obj,bool& a_created){
681   iro* obj;
682   if(!a_buffer.read_object(a_fac,a_args,obj,a_created)) {
683     a_buffer.out() << "tools::rroot::pointer_stream : read_object failed." << std::endl;
684     a_obj = 0;
685     a_created = false;
686     return false;
687   }
688   if(!obj) {
689     a_obj = 0;
690     a_created = false;
691   } else {
692     a_obj = (T*)obj->cast(a_T_class);
693     if(!a_obj) {
694       a_buffer.out() << "tools::rroot::pointer_stream : "
695                      << " tools::cast to " << a_T_class << " failed."
696                      << ". Object is a " << obj->s_cls() << "."
697                      << std::endl;
698       if(a_created) delete obj;
699       a_created = false;
700       return false;
701     }
702   }
703   return true;
704 }
705 
706 template <class T>
707 inline bool pointer_stream(buffer& a_buffer,ifac& a_fac,ifac::args& a_args,T*& a_obj,bool& a_created){
708   //return pointer_stream(a_buffer,a_fac,a_args,T::s_class(),a_obj,a_created);
709   return pointer_stream(a_buffer,a_fac,a_args,T::id_class(),a_obj,a_created);
710 }
711 
712 template <class T>
713 inline bool fixed_array_stream(buffer& a_buffer,int a_n,T*& a_v){
714   delete [] a_v;
715   a_v = 0;
716   char is_array;
717   if(!a_buffer.read(is_array)) return false;
718   if(!is_array) return true;
719   if(!a_n) return true;
720   a_v = new T[a_n];
721   if(!a_buffer.read_fast_array<T>(a_v,a_n)) {
722     delete [] a_v;
723     a_v = 0;
724     return false;
725   }
726   return true;
727 }
728 
729 }}
730 
731 #endif