g4tools  5.4.0
key
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_rroot_key
5 #define tools_rroot_key
6 
7 #include "rbuf"
8 #include "seek"
9 #include "date"
10 #include "ifile"
11 #include "../sout"
12 
13 #ifdef TOOLS_MEM
14 #include "../mem"
15 #endif
16 
17 #include <map>
18 #include <ostream>
19 #include <cstring> //memcpy
20 
21 //#include <zlib.h>
22 
23 #ifdef TOOLS_USE_CSZ
24 // CSZ code where used as default compressor in old CERN-ROOT, then it may be needed
25 // to read old file (as the pawdemo.root one).
26 //FIXME : arrange to have csz coming from the "outside" (as zip).
27 extern "C" {
28  void csz__Init_Inflate(long,unsigned char*,long,unsigned char*);
29  int csz__Inflate();
30  unsigned char* csz__obufptr();
31 }
32 #endif
33 
34 namespace tools {
35 namespace rroot {
36 
37 class key {
38  static uint32 class_version() {return 2;}
39 public:
40  static uint32 std_string_record_size(const std::string& x) {
41  // Returns size string will occupy on I/O buffer.
42  if (x.size() > 254)
43  return uint32(x.size()+sizeof(unsigned char)+sizeof(int));
44  else
45  return uint32(x.size()+sizeof(unsigned char));
46  }
47 
48 public:
49  key(std::ostream& a_out)
50  :m_out(a_out)
51  ,m_buf_size(0)
52  ,m_buffer(0)
53  // Record :
54  ,m_nbytes(0)
55  ,m_version(class_version())
56  ,m_object_size(0)
57  ,m_date(0)
58  ,m_key_length(0)
59  ,m_cycle(0)
60  ,m_seek_key(0)
62  //,m_object_class
63  //,m_object_name
64  //,m_object_title
65  {
66 #ifdef TOOLS_MEM
67  mem::increment(s_class().c_str());
68 #endif
70  //fDate.setDate(0);
71  }
72 
73  key(std::ostream& a_out,seek a_pos,uint32 a_nbytes)
74  :m_out(a_out)
75  ,m_buf_size(0)
76  ,m_buffer(0)
77  // Record :
78  ,m_nbytes(a_nbytes) //key len + compressed object size
79  ,m_version(class_version())
80  ,m_object_size(0)
81  ,m_date(0)
82  ,m_key_length(0)
83  ,m_cycle(0)
84  ,m_seek_key(a_pos)
86  //,m_object_class
87  //,m_object_name
88  //,m_object_title
89  {
90 #ifdef TOOLS_MEM
91  mem::increment(s_class().c_str());
92 #endif
94  m_buffer = new char[a_nbytes];
95  if(!m_buffer) {
96  m_out << "tools::rroot::key::key(cpcstor) :"
97  << " can't alloc " << a_nbytes << "."
98  << std::endl;
99  } else {
100  m_buf_size = a_nbytes;
101  }
102  }
103  virtual ~key(){
104  delete [] m_buffer;
105 #ifdef TOOLS_MEM
106  mem::decrement(s_class().c_str());
107 #endif
108  }
109 protected:
110  key(const key& a_from)
111  :m_out(a_from.m_out)
112  ,m_buf_size(0)
113  ,m_buffer(0)
114  ,m_nbytes(a_from.m_nbytes)
115  ,m_version(a_from.m_version)
117  ,m_date(a_from.m_date)
118  ,m_key_length(a_from.m_key_length)
119  ,m_cycle(a_from.m_cycle)
120  ,m_seek_key(a_from.m_seek_key)
125  {
126 #ifdef TOOLS_MEM
127  mem::increment(s_class().c_str());
128 #endif
129  if(a_from.m_buf_size && a_from.m_buffer) {
130  m_buffer = new char[a_from.m_buf_size];
131  if(!m_buffer) {
132  m_out << "tools::rroot::key::key(cpcstor) :"
133  << " can't alloc " << a_from.m_buf_size << "."
134  << std::endl;
135  } else {
136  m_buf_size = a_from.m_buf_size;
137  ::memcpy(m_buffer,a_from.m_buffer,a_from.m_buf_size);
138  }
139  }
140  }
141 public:
142  key& operator=(const key& a_from){
143  if(&a_from==this) return *this;
144  m_nbytes = a_from.m_nbytes;
145  m_version = a_from.m_version;
146  m_object_size = a_from.m_object_size;
147  m_date = a_from.m_date;
148  m_key_length = a_from.m_key_length;
149  m_cycle = a_from.m_cycle;
150  m_seek_key = a_from.m_seek_key;
153  m_object_name = a_from.m_object_name;
155 
156  delete [] m_buffer;
157  m_buffer = 0;
158  m_buf_size = 0;
159 
160  if(a_from.m_buf_size && a_from.m_buffer) {
161  m_buffer = new char[a_from.m_buf_size];
162  if(!m_buffer) {
163  m_out << "tools::rroot::key::operator=() :"
164  << " can't alloc " << a_from.m_buf_size << "."
165  << std::endl;
166  } else {
167  m_buf_size = a_from.m_buf_size;
168  ::memcpy(m_buffer,a_from.m_buffer,a_from.m_buf_size);
169  }
170  }
171 
172  return *this;
173  }
174 
175 public:
176  std::ostream& out() const {return m_out;}
177 
178  uint32 nbytes() const {return m_nbytes;}
179  seek seek_key() const {return m_seek_key;}
180  uint32 object_size() const {return m_object_size;}
181 
182  const std::string& object_name() const {return m_object_name;}
183  const std::string& object_title() const {return m_object_title;}
184  const std::string& object_class() const {return m_object_class;}
185 
186  bool read_file(ifile& a_file){
187  // Read the key structure from the file.
188  if(!a_file.set_pos(m_seek_key)) return false;
189  if(!a_file.read_buffer(m_buffer,m_nbytes)) return false;
190  if(a_file.verbose()) {
191  m_out << "tools::rroot::key::read_file :"
192  << " reading " << m_nbytes << " bytes"
193  << " at position " << m_seek_key
194  << "."
195  << std::endl;
196  }
197  return true;
198  }
199 
200  char* buf() const {return m_buffer;}
201  char* data_buffer() const {return m_buffer + m_key_length;}
202  const char* eob() const {return m_buffer + m_buf_size;}
203  uint32 buf_size() const {return m_buf_size;}
204  uint32 key_length() const {return m_key_length;}
205 
206  bool from_buffer(bool a_byte_swap,const char* aEOB,char*& a_pos,bool a_verbose) {
207  rbuf rb(m_out,a_byte_swap,aEOB,a_pos);
208  int _nbytes;
209  if(!rb.read(_nbytes)) return false;
210 /*
211  if(m_nbytes) {
212  if(_nbytes!=int(m_nbytes)) {
213  out << "tools::rroot::key::from_buffer :"
214  << " nbytes not consistent."
215  << " read " << _nbytes
216  << ", expected " << m_nbytes
217  << ". Continue with " << _nbytes
218  << std::endl;
219  m_nbytes = _nbytes;
220  }
221  } else {
222 */
223  m_nbytes = _nbytes;
224  //}
225  short version;
226  if(!rb.read(version)) return false;
227  m_version = version;
228  {int v;
229  if(!rb.read(v)) return false;
230  m_object_size = v;}
231  unsigned int _date;
232  if(!rb.read(_date)) return false;
233  //fDate.setDate(_date);
234  {short v;
235  if(!rb.read(v)) return false;
236  m_key_length = v;}
237  {short v;
238  if(!rb.read(v)) return false;
239  m_cycle = v;}
240  if(version>(short)big_file_version_tag()) {
241  if(!rb.read(m_seek_key)) return false;
242  if(!rb.read(m_seek_parent_dir)) return false;
243  } else {
244  {seek32 i;
245  if(!rb.read(i)) return false;
246  m_seek_key = i;}
247  {seek32 i;
248  if(!rb.read(i)) return false;
249  m_seek_parent_dir = i;}
250  }
251  if(!rb.read(m_object_class)) return false;
252  if(!rb.read(m_object_name)) return false;
253  if(!rb.read(m_object_title)) return false;
254  if(a_verbose) {
255  m_out << "tools::rroot::key::from_buffer :"
256  << " nbytes : " << m_nbytes
257  << ", object class : " << sout(m_object_class)
258  << ", object name : " << sout(m_object_name)
259  << ", object title : " << sout(m_object_title)
260  << ", object size : " << m_object_size
261  << "."
262  << std::endl;
263  }
264  return true;
265  }
266 
267  char* get_object_buffer(ifile& a_file,uint32& a_size) {
268  if(!m_key_length) {
269  m_out << "tools::rroot::key::get_object_buffer :"
270  << " WARNING : m_key_length is zero."
271  << std::endl;
272  //delete [] m_buffer;
273  //m_buffer = 0;
274  //m_buf_size = 0;
275  //a_size = 0;
276  //return 0;
277  }
278  if(!m_nbytes) {
279  m_out << "tools::rroot::key::get_object_buffer :"
280  << " m_nbytes is zero."
281  << std::endl;
282  delete [] m_buffer;
283  m_buffer = 0;
284  m_buf_size = 0;
285  a_size = 0;
286  return 0;
287  }
288  if(!m_object_size) {
289  m_out << "tools::rroot::key::get_object_buffer :"
290  << " WARNING : m_object_size is zero."
291  << std::endl;
292  }
293 
294  if(a_file.verbose()) {
295  m_out << "tools::rroot::key::get_object_buffer :"
296  << " m_nbytes : " << m_nbytes
297  << " m_key_length : " << m_key_length
298  << " m_object_size : " << m_object_size << "."
299  << " m_seek_key : " << m_seek_key << "."
300  << std::endl;
301  }
302 
304  delete [] m_buffer;
306  if(m_buf_size<m_nbytes) {
307  m_out << "tools::rroot::key::get_object_buffer :"
308  << " WARNING : m_buf_size<m_nbytes."
309  << " m_buf_size " << m_buf_size
310  << " m_nbytes " << m_nbytes
311  << ". Raise m_buf_size to " << m_nbytes << "."
312  << std::endl;
313  m_buf_size = m_nbytes; //for read_file()
314  }
315  m_buffer = new char[m_buf_size];
316  if(!m_buffer) {
317  m_out << "tools::rroot::key::get_object_buffer :"
318  << " can't alloc " << m_buf_size
319  << std::endl;
320  m_buffer = 0;
321  m_buf_size = 0;
322  a_size = 0;
323  return 0;
324  }
325 
326  if(!read_file(a_file)) {
327  delete [] m_buffer;
328  m_buffer = 0;
329  m_buf_size = 0;
330  a_size = 0;
331  return 0;
332  }
333 
334  } else {
335  // have to decompress. Need a second buffer.
336 
338  char* decbuf = new char[decsiz];
339  if(!decbuf) {
340  m_out << "tools::rroot::key::get_object_buffer :"
341  << " can't alloc " << decsiz
342  << std::endl;
343  a_size = 0;
344  return 0;
345  }
346 
347  delete [] m_buffer;
348  m_buffer = new char[m_nbytes];
350  if(!read_file(a_file)) {
351  delete [] decbuf;
352  decbuf = 0;
353  delete [] m_buffer;
354  m_buffer = 0;
355  m_buf_size = 0;
356  a_size = 0;
357  return 0;
358  }
359 
360  ::memcpy(decbuf,m_buffer,m_key_length);
361 
362  // decompress :
363  unsigned char* objbuf = (unsigned char*)(decbuf+m_key_length);
364  unsigned char* bufcur = (unsigned char*)(m_buffer+m_key_length);
365  int nout = 0;
366  uint32 noutot = 0;
367  while(true) {
368  int nin = 9 + ((int)bufcur[3] | ((int)bufcur[4] << 8) | ((int)bufcur[5] << 16));
369  int nbuf = (int)bufcur[6] | ((int)bufcur[7] << 8) | ((int)bufcur[8] << 16);
370  if(!unzip(m_out,a_file,nin,bufcur,nbuf,objbuf,nout)) break;
371  if(!nout) break;
372  noutot += nout;
373  if(noutot >= m_object_size) break;
374  bufcur += nin;
375  objbuf += nout;
376  }
377 
378  delete [] m_buffer;
379  m_buffer = 0;
380  m_buf_size = 0;
381 
382  if(!noutot) {
383  m_out << "tools::rroot::key::get_object_buffer :"
384  << " nothing from decompression."
385  << std::endl;
386  delete [] decbuf;
387  decbuf = 0;
388  a_size = 0;
389  return 0;
390  }
391  if(noutot!=m_object_size) {
392  m_out << "tools::rroot::key::get_object_buffer :"
393  << " decompression mismatch."
394  << " noutot " << noutot
395  << " m_object_size " << m_object_size
396  << std::endl;
397  delete [] decbuf;
398  decbuf = 0;
399  a_size = 0;
400  return 0;
401  }
402 
403  m_buffer = decbuf;
404  m_buf_size = decsiz;
405 
406  }
407  a_size = m_object_size;
408  return m_buffer+m_key_length;
409  }
410  //NOTE : print is a Python keyword.
411  void dump(std::ostream& a_out) const {
412  a_out << "class : " << sout(m_object_class)
413  << ", name : " << sout(m_object_name)
414  << ", title : " << sout(m_object_title)
415  << ", size : " << m_object_size
416  << "."
417  << std::endl;
418  }
419 
420 protected:
421  static const uint32 START_BIG_FILE = 2000000000;
422 protected:
423  uint32 record_size(uint32 a_version) const {
424  // Return the size in bytes of the key header structure.
425  uint32 _nbytes = sizeof(m_nbytes);
426  _nbytes += sizeof(short); //2
427  _nbytes += sizeof(m_object_size);
428  _nbytes += sizeof(date);
429  _nbytes += sizeof(m_key_length);
430  _nbytes += sizeof(m_cycle); //2+4*4=18
431  if(a_version>big_file_version_tag()) {
432  _nbytes += sizeof(seek);
433  _nbytes += sizeof(seek); //18+2*8=34
434  } else {
435  _nbytes += sizeof(seek32);
436  _nbytes += sizeof(seek32); //18+2*4=26
437  }
441  //::printf("debug : record_size %d\n",_nbytes);
442  return _nbytes;
443  }
444 
445  bool unzip(std::ostream& a_out,ifile& a_file,
446  int a_srcsize,unsigned char* a_src,int a_tgtsize,unsigned char* a_tgt,int& a_irep) {
447 
448  // Author: E.Chernyaev (IHEP/Protvino)
449  // Input: scrsize - size of input buffer
450  // src - input buffer
451  // tgtsize - size of target buffer
452  //
453  // Output: tgt - target buffer (decompressed)
454  // irep - size of decompressed data
455  // 0 - if error
456 
457  a_irep = 0;
458 
459  // C H E C K H E A D E R
460  const int HDRSIZE = 9;
461 
462  if (a_srcsize < HDRSIZE) {
463  a_out << "tools::rroot::key::unzip : too small source" << std::endl;
464  return false;
465  }
466 
467  unsigned char DEFLATE = 8;
468 
469  if ((a_src[0] != 'C' && a_src[0] != 'Z') ||
470  (a_src[1] != 'S' && a_src[1] != 'L') ||
471  a_src[2] != DEFLATE) {
472  a_out << "tools::rroot::key::unzip : error in header" << std::endl;
473  return false;
474  }
475 
476  long _ibufcnt = (long)a_src[3] | ((long)a_src[4] << 8) | ((long)a_src[5] << 16);
477  long isize = (long)a_src[6] | ((long)a_src[7] << 8) | ((long)a_src[8] << 16);
478 
479  if(a_tgtsize<isize) {
480  a_out << "tools::rroot::key::unzip : too small target." << std::endl;
481  return false;
482  }
483 
484  if(_ibufcnt + HDRSIZE != a_srcsize) {
485  a_out << "tools::rroot::key::unzip :"
486  << " discrepancy in source length." << std::endl;
487  return false;
488  }
489 
490  // D E C O M P R E S S D A T A
491 
492  if (a_src[0] == 'Z' && a_src[1] == 'L') { //compressed with zlib.
493  decompress_func func;
494  if(!a_file.unziper('Z',func)) {
495  a_out << "tools::rroot::key::unzip : "
496  << " zlib unziper not found." << std::endl;
497  return false;
498  }
499 
500  unsigned int irep;
501  char* src = (char*)(a_src + HDRSIZE);
502  if(!func(a_out,
503  (unsigned int)a_srcsize,src,
504  (unsigned int)a_tgtsize,(char*)a_tgt,irep)) {
505  a_out << "tools::rroot::key::unzip : "
506  << " unzip function failed." << std::endl;
507  a_irep = 0;
508  return false;
509  }
510  a_irep = irep;
511 
512 #ifdef TOOLS_USE_CSZ
513  } else if (a_src[0] == 'C' && a_src[1] == 'S') {
514  //compressed with Chernyaev & Smirnov
515 
516  csz__Init_Inflate(_ibufcnt,a_src + HDRSIZE,a_tgtsize,a_tgt);
517 
518  if (csz__Inflate()) {
519  a_out << "tools::rroot::key::unzip :"
520  << " error during decompression." << std::endl;
521  return false;
522  }
523 
524  unsigned char* obufptr = csz__obufptr();
525 
526  // if (obufptr - a_tgt != isize) {
527  // There are some rare cases when a few more bytes are required
528  if (obufptr - a_tgt > a_tgtsize) {
529  a_out << "tools::rroot::key::_unzip :"
530  << " discrepancy " << (int)(obufptr - a_tgt)
531  << " with initial size: " << (int)isize
532  << ", tgtsize= " << a_tgtsize
533  << std::endl;
534  a_irep = int(obufptr - a_tgt);
535  //return false;
536  }
537  a_irep = isize;
538 
539  //a_out << "tools::rroot::key::unzip : CS : ok "
540  // << a_irep << std::endl;
541 #endif
542  } else {
543  a_out << "tools::rroot::key::_unzip : unknown a_src[0,1]."
544  << " [0] = " << a_src[0] << ", [1] = " << a_src[1]
545  << std::endl;
546  a_irep = 0;
547  return false;
548  }
549  return true;
550  }
551 
552  static const std::string& s_class() {
553  static const std::string s_v("tools::rroot::key");
554  return s_v;
555  }
556 protected:
557  std::ostream& m_out;
559  char* m_buffer;
560  // Record (stored in file) :
561  uint32 m_nbytes; //Number of bytes for the object on file
562  uint32 m_version; //Key version identifier
563  uint32 m_object_size; //Length of uncompressed object in bytes
564  date m_date; //Date/Time of insertion in file
565  uint16 m_key_length; //Number of bytes for the key itself
566  uint16 m_cycle; //Cycle number
567  seek m_seek_key; //Location of object on file
568  seek m_seek_parent_dir; //Location of parent directory on file
569  std::string m_object_class; //Object Class name.
570  std::string m_object_name; //name of the object.
571  std::string m_object_title; //title of the object.
572 };
573 
574 }}
575 
576 #endif
577 
578 //doc :
580 // //
581 // The Key class includes functions to book space on a file, //
582 // to create I/O buffers, to fill these buffers //
583 // to compress/uncompress data buffers. //
584 // //
585 // Before saving (making persistent) an object on a file, a key must //
586 // be created. The key structure contains all the information to //
587 // uniquely identify a persistent object on a file. //
588 // fNbytes = number of bytes for the compressed object+key //
589 // version of the Key class //
590 // fObjlen = Length of uncompressed object //
591 // fDatime = Date/Time when the object was written //
592 // fKeylen = number of bytes for the key structure //
593 // fCycle = cycle number of the object //
594 // fSeekKey = Address of the object on file (points to fNbytes) //
595 // This is a redundant information used to cross-check //
596 // the data base integrity. //
597 // fSeekPdir = Pointer to the directory supporting this object //
598 // fClassName = Object class name //
599 // fName = name of the object //
600 // fTitle = title of the object //
601 // //
602 // The Key class is used by ROOT to: //
603 // - to write an object in the Current Directory //
604 // - to write a new ntuple buffer //
605 // //
tools::rroot::key::~key
virtual ~key()
Definition: key:103
rbuf
tools::rroot::ifile::set_pos
virtual bool set_pos(seek=0, from=begin)=0
tools::rroot::key::m_object_title
std::string m_object_title
Definition: key:571
tools::rroot::key::seek_key
seek seek_key() const
Definition: key:179
tools::rroot::seek32
int seek32
Definition: seek:17
tools::rroot::key::m_object_size
uint32 m_object_size
Definition: key:563
tools::rroot::key::m_version
uint32 m_version
Definition: key:562
tools::rroot::key::key
key(const key &a_from)
Definition: key:110
tools::rroot::date
unsigned int date
Definition: date:10
tools::rroot::key::object_name
const std::string & object_name() const
Definition: key:182
tools::rroot::key::m_object_class
std::string m_object_class
Definition: key:569
tools::rroot::key::object_size
uint32 object_size() const
Definition: key:180
tools::rroot::key::buf_size
uint32 buf_size() const
Definition: key:203
tools::rroot::big_file_version_tag
uint32 big_file_version_tag()
Definition: seek:19
tools::rroot::key::m_out
std::ostream & m_out
Definition: key:557
tools::rroot::key::s_class
static const std::string & s_class()
Definition: key:552
tools::rroot::key::eob
const char * eob() const
Definition: key:202
ifile
tools::rroot::key::unzip
bool unzip(std::ostream &a_out, ifile &a_file, int a_srcsize, unsigned char *a_src, int a_tgtsize, unsigned char *a_tgt, int &a_irep)
Definition: key:445
tools::rroot::key::operator=
key & operator=(const key &a_from)
Definition: key:142
tools::rroot::key::m_buffer
char * m_buffer
Definition: key:559
tools::rroot::key::get_object_buffer
char * get_object_buffer(ifile &a_file, uint32 &a_size)
Definition: key:267
tools::rroot::key::buf
char * buf() const
Definition: key:200
tools::sout
Definition: sout:17
tools::version
unsigned int version()
Definition: version:14
tools::rroot::seek
int64 seek
Definition: seek:16
tools::rroot::key::nbytes
uint32 nbytes() const
Definition: key:178
tools::rroot::key::m_nbytes
uint32 m_nbytes
Definition: key:561
tools::rroot::key::m_date
date m_date
Definition: key:564
tools::rroot::rbuf
Definition: rbuf:22
tools::rroot::key::m_key_length
uint16 m_key_length
Definition: key:565
tools::rroot::key::START_BIG_FILE
static const uint32 START_BIG_FILE
Definition: key:421
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::rroot::ifile
Definition: ifile:16
tools::rroot::key::dump
void dump(std::ostream &a_out) const
Definition: key:411
tools::uint16
unsigned short uint16
Definition: typedefs:102
tools::decompress_func
bool(* decompress_func)(std::ostream &, unsigned int, const char *, unsigned int, char *, unsigned int &)
Definition: press_func:13
seek
tools::rroot::key::key_length
uint32 key_length() const
Definition: key:204
tools::rroot::key::key
key(std::ostream &a_out)
Definition: key:49
tools::rroot::rbuf::read
bool read(unsigned char &a_x)
Definition: rbuf:146
tools::rroot::key
Definition: key:37
tools::rroot::key::m_seek_key
seek m_seek_key
Definition: key:567
tools::rroot::key::m_object_name
std::string m_object_name
Definition: key:570
tools::rroot::ifile::read_buffer
virtual bool read_buffer(char *, uint32)=0
tools::rroot::key::object_title
const std::string & object_title() const
Definition: key:183
tools::rroot::key::key
key(std::ostream &a_out, seek a_pos, uint32 a_nbytes)
Definition: key:73
tools::rroot::key::out
std::ostream & out() const
Definition: key:176
tools::rroot::key::m_cycle
uint16 m_cycle
Definition: key:566
tools::rroot::key::object_class
const std::string & object_class() const
Definition: key:184
tools::uint32
unsigned int uint32
Definition: typedefs:71
tools::rroot::key::from_buffer
bool from_buffer(bool a_byte_swap, const char *aEOB, char *&a_pos, bool a_verbose)
Definition: key:206
tools::rroot::key::data_buffer
char * data_buffer() const
Definition: key:201
date
tools::rroot::key::m_buf_size
uint32 m_buf_size
Definition: key:558
tools::rroot::key::std_string_record_size
static uint32 std_string_record_size(const std::string &x)
Definition: key:40
tools::rroot::key::m_seek_parent_dir
seek m_seek_parent_dir
Definition: key:568
tools::rroot::ifile::verbose
virtual bool verbose() const =0
tools::rroot::key::record_size
uint32 record_size(uint32 a_version) const
Definition: key:423
tools::rroot::ifile::unziper
virtual bool unziper(char, decompress_func &) const =0
tools::rroot::key::read_file
bool read_file(ifile &a_file)
Definition: key:186