Logo ROOT  
Reference Guide
TBufferText.cxx
Go to the documentation of this file.
1 // $Id$
2 // Author: Sergey Linev 21.12.2017
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**
13 \class TBufferText
14 \ingroup IO
15 
16 Base class for text-based streamers like TBufferJSON or TBufferXML
17 Special actions list will use methods, introduced in this class.
18 
19 Idea to have equivalent methods names in TBufferFile and TBufferText, that
20 actions list for both are the same.
21 */
22 
23 #include "TBufferText.h"
24 
25 #include "TStreamerInfo.h"
26 #include "TStreamerElement.h"
27 #include "TStreamerInfoActions.h"
28 #include "TFile.h"
29 #include "TVirtualMutex.h"
30 #include "TInterpreter.h"
31 #include "TExMap.h"
32 #include "TError.h"
33 #include "snprintf.h"
34 
36 
37 const char *TBufferText::fgFloatFmt = "%e";
38 const char *TBufferText::fgDoubleFmt = "%.14e";
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 /// Default constructor
42 
44 {
45 }
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 /// Normal constructor
49 
51 {
52  fBufSize = 1000000000;
53 
54  SetParent(parent);
56 }
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// destructor
60 
62 {
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
67 /// The collection needs to be a split TClonesArray or a split vector of pointers.
68 
70 {
71  TVirtualStreamerInfo *info = sequence.fStreamerInfo;
72  IncrementLevel(info);
73 
74  if (gDebug) {
75  // loop on all active members
76  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
77  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin(); iter != end;
78  ++iter) {
79  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
80  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
81  (*iter).PrintDebug(*this, obj);
82  (*iter)(*this, obj);
83  }
84  } else {
85  // loop on all active members
86  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
87  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin(); iter != end;
88  ++iter) {
89  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
90  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
91  (*iter)(*this, obj);
92  }
93  }
94  DecrementLevel(info);
95  return 0;
96 }
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 /// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
100 /// The collection needs to be a split TClonesArray or a split vector of pointers.
101 
103  void *end_collection)
104 {
105  TVirtualStreamerInfo *info = sequence.fStreamerInfo;
106  IncrementLevel(info);
107 
108  if (gDebug) {
109  // loop on all active members
110  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
111  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin(); iter != end;
112  ++iter) {
113  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
114  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
115  (*iter).PrintDebug(
116  *this, *(char **)start_collection); // Warning: This limits us to TClonesArray and vector of pointers.
117  (*iter)(*this, start_collection, end_collection);
118  }
119  } else {
120  // loop on all active members
121  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
122  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin(); iter != end;
123  ++iter) {
124  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
125  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
126  (*iter)(*this, start_collection, end_collection);
127  }
128  }
129  DecrementLevel(info);
130  return 0;
131 }
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 /// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
135 
137  void *end_collection)
138 {
139  TVirtualStreamerInfo *info = sequence.fStreamerInfo;
140  IncrementLevel(info);
141 
143  if (gDebug) {
144 
145  // Get the address of the first item for the PrintDebug.
146  // (Performance is not essential here since we are going to print to
147  // the screen anyway).
148  void *arr0 = loopconfig->GetFirstAddress(start_collection, end_collection);
149  // loop on all active members
150  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
151  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin(); iter != end;
152  ++iter) {
153  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
154  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
155  (*iter).PrintDebug(*this, arr0);
156  (*iter)(*this, start_collection, end_collection, loopconfig);
157  }
158  } else {
159  // loop on all active members
160  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
161  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin(); iter != end;
162  ++iter) {
163  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
164  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
165  (*iter)(*this, start_collection, end_collection, loopconfig);
166  }
167  }
168  DecrementLevel(info);
169  return 0;
170 }
171 
172 ////////////////////////////////////////////////////////////////////////////////
173 /// Function called by the Streamer functions to serialize object at p
174 /// to buffer b. The optional argument info may be specified to give an
175 /// alternative StreamerInfo instead of using the default StreamerInfo
176 /// automatically built from the class definition.
177 /// For more information, see class TStreamerInfo.
178 
179 Int_t TBufferText::WriteClassBuffer(const TClass *cl, void *pointer)
180 {
181  // build the StreamerInfo if first time for the class
182  TStreamerInfo *sinfo = (TStreamerInfo *)const_cast<TClass *>(cl)->GetCurrentStreamerInfo();
183  if (!sinfo) {
184  // Have to be sure between the check and the taking of the lock if the current streamer has changed
186  sinfo = (TStreamerInfo *)const_cast<TClass *>(cl)->GetCurrentStreamerInfo();
187  if (!sinfo) {
188  const_cast<TClass *>(cl)->BuildRealData(pointer);
189  sinfo = new TStreamerInfo(const_cast<TClass *>(cl));
190  const_cast<TClass *>(cl)->SetCurrentStreamerInfo(sinfo);
191  const_cast<TClass *>(cl)->RegisterStreamerInfo(sinfo);
192  if (gDebug > 0)
193  Info("WriteClassBuffer", "Creating StreamerInfo for class: %s, version: %d", cl->GetName(),
194  cl->GetClassVersion());
195  sinfo->Build();
196  }
197  } else if (!sinfo->IsCompiled()) {
199  // Redo the test in case we have been victim of a data race on fIsCompiled.
200  if (!sinfo->IsCompiled()) {
201  const_cast<TClass *>(cl)->BuildRealData(pointer);
202  sinfo->BuildOld();
203  }
204  }
205 
206  // write the class version number and reserve space for the byte count
207  UInt_t R__c = WriteVersion(cl, kTRUE);
208 
209  // NOTE: In the future Philippe wants this to happen via a custom action
210  TagStreamerInfo(sinfo);
211  ApplySequence(*(sinfo->GetWriteTextActions()), (char *)pointer);
212 
213  // write the byte count at the start of the buffer
214  SetByteCount(R__c, kTRUE);
215 
216  if (gDebug > 2)
217  Info("WriteClassBuffer", "class: %s version %d has written %d bytes", cl->GetName(), cl->GetClassVersion(),
218  UInt_t(fBufCur - fBuffer) - R__c - (UInt_t)sizeof(UInt_t));
219  return 0;
220 }
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 /// Deserialize information from a buffer into an object.
224 ///
225 /// Note: This function is called by the xxx::Streamer() functions in
226 /// rootcint-generated dictionaries.
227 /// This function assumes that the class version and the byte count
228 /// information have been read.
229 ///
230 /// \param[in] version The version number of the class
231 /// \param[in] start The starting position in the buffer b
232 /// \param[in] count The number of bytes for this object in the buffer
233 ///
234 
235 Int_t TBufferText::ReadClassBuffer(const TClass *cl, void *pointer, Int_t version, UInt_t start, UInt_t count,
236  const TClass *onFileClass)
237 {
238 
239  //---------------------------------------------------------------------------
240  // The ondisk class has been specified so get foreign streamer info
241  /////////////////////////////////////////////////////////////////////////////
242 
243  TStreamerInfo *sinfo = nullptr;
244  if (onFileClass) {
245  sinfo = (TStreamerInfo *)cl->GetConversionStreamerInfo(onFileClass, version);
246  if (!sinfo) {
247  Error("ReadClassBuffer",
248  "Could not find the right streamer info to convert %s version %d into a %s, object skipped at offset %d",
249  onFileClass->GetName(), version, cl->GetName(), Length());
250  CheckByteCount(start, count, onFileClass);
251  return 0;
252  }
253  }
254  //---------------------------------------------------------------------------
255  // Get local streamer info
256  /////////////////////////////////////////////////////////////////////////////
257  /// The StreamerInfo should exist at this point.
258 
259  else {
261  auto infos = cl->GetStreamerInfos();
262  auto ninfos = infos->GetSize();
263  if (version < -1 || version >= ninfos) {
264  Error("ReadBuffer1", "class: %s, attempting to access a wrong version: %d, object skipped at offset %d",
265  cl->GetName(), version, Length());
266  CheckByteCount(start, count, cl);
267  return 0;
268  }
269  sinfo = (TStreamerInfo *)infos->At(version);
270  if (!sinfo) {
271  // Unless the data is coming via a socket connection from with schema evolution
272  // (tracking) was not enabled. So let's create the StreamerInfo if it is the
273  // one for the current version, otherwise let's complain ...
274  // We could also get here if there old class version was '1' and the new class version is higher than 1
275  // AND the checksum is the same.
276  if (version == cl->GetClassVersion() || version == 1) {
277  const_cast<TClass *>(cl)->BuildRealData(pointer);
278  // This creation is alright since we just checked within the
279  // current 'locked' section.
280  sinfo = new TStreamerInfo(const_cast<TClass *>(cl));
281  const_cast<TClass *>(cl)->RegisterStreamerInfo(sinfo);
282  if (gDebug > 0)
283  Info("ReadClassBuffer", "Creating StreamerInfo for class: %s, version: %d", cl->GetName(), version);
284  sinfo->Build();
285  } else if (version == 0) {
286  // When the object was written the class was version zero, so
287  // there is no StreamerInfo to be found.
288  // Check that the buffer position corresponds to the byte count.
289  CheckByteCount(start, count, cl);
290  return 0;
291  } else {
292  Error("ReadClassBuffer",
293  "Could not find the StreamerInfo for version %d of the class %s, object skipped at offset %d",
294  version, cl->GetName(), Length());
295  CheckByteCount(start, count, cl);
296  return 0;
297  }
298  } else if (!sinfo->IsCompiled()) { // Note this read is protected by the above lock.
299  // Streamer info has not been compiled, but exists.
300  // Therefore it was read in from a file and we have to do schema evolution.
301  const_cast<TClass *>(cl)->BuildRealData(pointer);
302  sinfo->BuildOld();
303  }
304  }
305 
306  // Deserialize the object.
307  ApplySequence(*(sinfo->GetReadTextActions()), (char *)pointer);
308  if (sinfo->IsRecovered())
309  count = 0;
310 
311  // Check that the buffer position corresponds to the byte count.
312  CheckByteCount(start, count, cl);
313  return 0;
314 }
315 
316 ////////////////////////////////////////////////////////////////////////////////
317 /// Deserialize information from a buffer into an object.
318 ///
319 /// Note: This function is called by the xxx::Streamer()
320 /// functions in rootcint-generated dictionaries.
321 ///
322 
323 Int_t TBufferText::ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onFileClass)
324 {
325  // Read the class version from the buffer.
326  UInt_t R__s = 0; // Start of object.
327  UInt_t R__c = 0; // Count of bytes.
328  Version_t version;
329 
330  if (onFileClass)
331  version = ReadVersion(&R__s, &R__c, onFileClass);
332  else
333  version = ReadVersion(&R__s, &R__c, cl);
334 
335  Bool_t v2file = kFALSE;
336  TFile *file = (TFile *)GetParent();
337  if (file && file->GetVersion() < 30000) {
338  version = -1; // This is old file
339  v2file = kTRUE;
340  }
341 
342  //---------------------------------------------------------------------------
343  // The ondisk class has been specified so get foreign streamer info
344  /////////////////////////////////////////////////////////////////////////////
345 
346  TStreamerInfo *sinfo = nullptr;
347  if (onFileClass) {
348  sinfo = (TStreamerInfo *)cl->GetConversionStreamerInfo(onFileClass, version);
349  if (!sinfo) {
350  Error("ReadClassBuffer",
351  "Could not find the right streamer info to convert %s version %d into a %s, object skipped at offset %d",
352  onFileClass->GetName(), version, cl->GetName(), Length());
353  CheckByteCount(R__s, R__c, onFileClass);
354  return 0;
355  }
356  }
357  //---------------------------------------------------------------------------
358  // Get local streamer info
359  /////////////////////////////////////////////////////////////////////////////
360  /// The StreamerInfo should exist at this point.
361 
362  else {
363  TStreamerInfo *guess = (TStreamerInfo *)cl->GetLastReadInfo();
364  if (guess && guess->GetClassVersion() == version) {
365  sinfo = guess;
366  } else {
367  // The last one is not the one we are looking for.
368  {
370 
371  const TObjArray *infos = cl->GetStreamerInfos();
372  Int_t infocapacity = infos->Capacity();
373  if (infocapacity) {
374  if (version < -1 || version >= infocapacity) {
375  Error("ReadClassBuffer",
376  "class: %s, attempting to access a wrong version: %d, object skipped at offset %d",
377  cl->GetName(), version, Length());
378  CheckByteCount(R__s, R__c, cl);
379  return 0;
380  }
381  sinfo = (TStreamerInfo *)infos->UncheckedAt(version);
382  if (sinfo) {
383  if (!sinfo->IsCompiled()) {
384  // Streamer info has not been compiled, but exists.
385  // Therefore it was read in from a file and we have to do schema evolution?
387  const_cast<TClass *>(cl)->BuildRealData(pointer);
388  sinfo->BuildOld();
389  }
390  // If the compilation succeeded, remember this StreamerInfo.
391  // const_cast okay because of the lock on gInterpreterMutex.
392  if (sinfo->IsCompiled())
393  const_cast<TClass *>(cl)->SetLastReadInfo(sinfo);
394  }
395  }
396  }
397 
398  if (!sinfo) {
399  // Unless the data is coming via a socket connection from with schema evolution
400  // (tracking) was not enabled. So let's create the StreamerInfo if it is the
401  // one for the current version, otherwise let's complain ...
402  // We could also get here when reading a file prior to the introduction of StreamerInfo.
403  // We could also get here if there old class version was '1' and the new class version is higher than 1
404  // AND the checksum is the same.
405  if (v2file || version == cl->GetClassVersion() || version == 1) {
407 
408  // We need to check if another thread did not get here first
409  // and did the StreamerInfo creation already.
410  auto infos = cl->GetStreamerInfos();
411  auto ninfos = infos->GetSize();
412  if (!(version < -1 || version >= ninfos)) {
413  sinfo = (TStreamerInfo *)infos->At(version);
414  }
415  if (!sinfo) {
416  const_cast<TClass *>(cl)->BuildRealData(pointer);
417  sinfo = new TStreamerInfo(const_cast<TClass *>(cl));
418  sinfo->SetClassVersion(version);
419  const_cast<TClass *>(cl)->RegisterStreamerInfo(sinfo);
420  if (gDebug > 0)
421  Info("ReadClassBuffer", "Creating StreamerInfo for class: %s, version: %d", cl->GetName(),
422  version);
423  if (v2file) {
424  sinfo->Build(); // Get the elements.
425  sinfo->Clear("build"); // Undo compilation.
426  sinfo->BuildEmulated(file); // Fix the types and redo compilation.
427  } else {
428  sinfo->Build();
429  }
430  }
431  } else if (version == 0) {
432  // When the object was written the class was version zero, so
433  // there is no StreamerInfo to be found.
434  // Check that the buffer position corresponds to the byte count.
435  CheckByteCount(R__s, R__c, cl);
436  return 0;
437  } else {
438  Error("ReadClassBuffer",
439  "Could not find the StreamerInfo for version %d of the class %s, object skipped at offset %d",
440  version, cl->GetName(), Length());
441  CheckByteCount(R__s, R__c, cl);
442  return 0;
443  }
444  }
445  }
446  }
447 
448  // deserialize the object
449  ApplySequence(*(sinfo->GetReadTextActions()), (char *)pointer);
450  if (sinfo->TStreamerInfo::IsRecovered())
451  R__c = 0; // 'TStreamerInfo::' avoids going via a virtual function.
452 
453  // Check that the buffer position corresponds to the byte count.
454  CheckByteCount(R__s, R__c, cl);
455 
456  if (gDebug > 2)
457  Info("ReadClassBuffer", "for class: %s has read %d bytes", cl->GetName(), R__c);
458 
459  return 0;
460 }
461 
462 ////////////////////////////////////////////////////////////////////////////////
463 /// stream object to/from buffer
464 
465 void TBufferText::StreamObject(void *obj, const std::type_info &typeinfo, const TClass * /* onFileClass */)
466 {
467  StreamObject(obj, TClass::GetClass(typeinfo));
468 }
469 
470 ////////////////////////////////////////////////////////////////////////////////
471 /// stream object to/from buffer
472 
473 void TBufferText::StreamObject(void *obj, const char *className, const TClass * /* onFileClass */)
474 {
475  StreamObject(obj, TClass::GetClass(className));
476 }
477 
479 {
480  // stream object to/from buffer
481 
482  StreamObject(obj, obj ? obj->IsA() : TObject::Class());
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// read a Float16_t from the buffer
487 
489 {
490  ReadFloat(*f);
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// read a Double32_t from the buffer
495 
497 {
498  ReadDouble(*d);
499 }
500 
501 ////////////////////////////////////////////////////////////////////////////////
502 /// Read a Double32_t from the buffer when the factor and minimun value have
503 /// been specified
504 /// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
505 /// Currently TBufferText does not optimize space in this case.
506 
507 void TBufferText::ReadWithFactor(Float_t *f, Double_t /* factor */, Double_t /* minvalue */)
508 {
509  ReadFloat(*f);
510 }
511 
512 ////////////////////////////////////////////////////////////////////////////////
513 /// Read a Float16_t from the buffer when the number of bits is specified
514 /// (explicitly or not)
515 /// see comments about Float16_t encoding at TBufferFile::WriteFloat16().
516 /// Currently TBufferText does not optimize space in this case.
517 
519 {
520  ReadFloat(*f);
521 }
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Read a Double32_t from the buffer when the factor and minimun value have
525 /// been specified
526 /// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
527 /// Currently TBufferText does not optimize space in this case.
528 
529 void TBufferText::ReadWithFactor(Double_t *d, Double_t /* factor */, Double_t /* minvalue */)
530 {
531  ReadDouble(*d);
532 }
533 
534 ////////////////////////////////////////////////////////////////////////////////
535 /// Read a Double32_t from the buffer when the number of bits is specified
536 /// (explicitly or not)
537 /// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
538 /// Currently TBufferText does not optimize space in this case.
539 
541 {
542  ReadDouble(*d);
543 }
544 
545 ////////////////////////////////////////////////////////////////////////////////
546 /// write a Float16_t to the buffer
547 
549 {
550  WriteFloat(*f);
551 }
552 
553 ////////////////////////////////////////////////////////////////////////////////
554 /// write a Double32_t to the buffer
555 
557 {
558  WriteDouble(*d);
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// Read array of Float16_t from buffer
563 
565 {
566  return ReadArray(f);
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 /// Read array of Double32_t from buffer
571 
573 {
574  return ReadArray(d);
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 /// Read array of Float16_t from buffer
579 
581 {
582  return ReadStaticArray(f);
583 }
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 /// Read array of Double32_t from buffer
587 
589 {
590  return ReadStaticArray(d);
591 }
592 
593 ////////////////////////////////////////////////////////////////////////////////
594 /// read array of Float16_t from buffer
595 
597 {
598  ReadFastArray(f, n);
599 }
600 
601 ////////////////////////////////////////////////////////////////////////////////
602 /// read array of Float16_t from buffer
603 
605 {
606  ReadFastArray(f, n);
607 }
608 
609 ////////////////////////////////////////////////////////////////////////////////
610 /// read array of Float16_t from buffer
611 
613 {
614  ReadFastArray(f, n);
615 }
616 
617 ////////////////////////////////////////////////////////////////////////////////
618 /// read array of Double32_t from buffer
619 
621 {
622  ReadFastArray(d, n);
623 }
624 
625 ////////////////////////////////////////////////////////////////////////////////
626 /// read array of Double32_t from buffer
627 
629 {
630  ReadFastArray(d, n);
631 }
632 
633 ////////////////////////////////////////////////////////////////////////////////
634 /// read array of Double32_t from buffer
635 
637 {
638  ReadFastArray(d, n);
639 }
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Write array of Float16_t to buffer
642 
644 {
645  WriteArray(f, n);
646 }
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 /// Write array of Double32_t to buffer
650 
652 {
653  WriteArray(d, n);
654 }
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 /// Write array of Float16_t to buffer
658 
660 {
661  WriteFastArray(f, n);
662 }
663 
664 ////////////////////////////////////////////////////////////////////////////////
665 /// Write array of Double32_t to buffer
666 
668 {
669  WriteFastArray(d, n);
670 }
671 
672 ////////////////////////////////////////////////////////////////////////////////
673 /// Skip class version from I/O buffer.
674 
676 {
677  ReadVersion(nullptr, nullptr, cl);
678 }
679 
680 ////////////////////////////////////////////////////////////////////////////////
681 /// Write data of base class.
682 
684 {
685  elem->WriteBuffer(*this, (char *)start);
686 }
687 
688 ////////////////////////////////////////////////////////////////////////////////
689 /// Read data of base class.
690 
692 {
693  elem->ReadBuffer(*this, (char *)start);
694 }
695 
696 ////////////////////////////////////////////////////////////////////////////////
697 /// method compress float string, excluding exp and/or move float point
698 /// - 1.000000e-01 -> 0.1
699 /// - 3.750000e+00 -> 3.75
700 /// - 3.750000e-03 -> 0.00375
701 /// - 3.750000e-04 -> 3.75e-4
702 /// - 1.100000e-10 -> 1.1e-10
703 
704 void TBufferText::CompactFloatString(char *sbuf, unsigned len)
705 {
706  char *pnt = nullptr, *exp = nullptr, *lastdecimal = nullptr, *s = sbuf;
707  bool negative_exp = false;
708  int power = 0;
709  while (*s && --len) {
710  switch (*s) {
711  case '.': pnt = s; break;
712  case 'E':
713  case 'e': exp = s; break;
714  case '-':
715  if (exp)
716  negative_exp = true;
717  break;
718  case '+': break;
719  default: // should be digits from '0' to '9'
720  if ((*s < '0') || (*s > '9'))
721  return;
722  if (exp)
723  power = power * 10 + (*s - '0');
724  else if (pnt && *s != '0')
725  lastdecimal = s;
726  break;
727  }
728  ++s;
729  }
730  if (*s)
731  return; // if end-of-string was not found
732 
733  if (!exp) {
734  // value without exponent like 123.4569000
735  if (pnt) {
736  if (lastdecimal)
737  *(lastdecimal + 1) = 0;
738  else
739  *pnt = 0;
740  }
741  } else if (power == 0) {
742  if (lastdecimal)
743  *(lastdecimal + 1) = 0;
744  else if (pnt)
745  *pnt = 0;
746  } else if (!negative_exp && pnt && exp && (exp - pnt > power)) {
747  // this is case of value 1.23000e+02
748  // we can move point and exclude exponent easily
749  for (int cnt = 0; cnt < power; ++cnt) {
750  char tmp = *pnt;
751  *pnt = *(pnt + 1);
752  *(++pnt) = tmp;
753  }
754  if (lastdecimal && (pnt < lastdecimal))
755  *(lastdecimal + 1) = 0;
756  else
757  *pnt = 0;
758  } else if (negative_exp && pnt && exp && (power < (s - exp))) {
759  // this is small negative exponent like 1.2300e-02
760  if (!lastdecimal)
761  lastdecimal = pnt;
762  *(lastdecimal + 1) = 0;
763  // copy most significant digit on the point place
764  *pnt = *(pnt - 1);
765 
766  for (char *pos = lastdecimal + 1; pos >= pnt; --pos)
767  *(pos + power) = *pos;
768  *(pnt - 1) = '0';
769  *pnt = '.';
770  for (int cnt = 1; cnt < power; ++cnt)
771  *(pnt + cnt) = '0';
772  } else if (pnt && exp) {
773  // keep exponent, but non-significant zeros
774  if (lastdecimal)
775  pnt = lastdecimal + 1;
776  // copy exponent sign
777  *pnt++ = *exp++;
778  if (*exp == '+')
779  ++exp;
780  else if (*exp == '-')
781  *pnt++ = *exp++;
782  // exclude zeros in the begin of exponent
783  while (*exp == '0')
784  ++exp;
785  while (*exp)
786  *pnt++ = *exp++;
787  *pnt = 0;
788  }
789 }
790 
791 ////////////////////////////////////////////////////////////////////////////////
792 /// set printf format for float/double members, default "%e"
793 /// to change format only for doubles, use SetDoubleFormat
794 
795 void TBufferText::SetFloatFormat(const char *fmt)
796 {
797  if (!fmt)
798  fmt = "%e";
799  fgFloatFmt = fmt;
800  fgDoubleFmt = fmt;
801 }
802 
803 ////////////////////////////////////////////////////////////////////////////////
804 /// return current printf format for float members, default "%e"
805 
807 {
808  return fgFloatFmt;
809 }
810 
811 ////////////////////////////////////////////////////////////////////////////////
812 /// set printf format for double members, default "%.14e"
813 /// use it after SetFloatFormat, which also overwrites format for doubles
814 
815 void TBufferText::SetDoubleFormat(const char *fmt)
816 {
817  if (!fmt)
818  fmt = "%.14e";
819  fgDoubleFmt = fmt;
820 }
821 
822 ////////////////////////////////////////////////////////////////////////////////
823 /// return current printf format for double members, default "%.14e"
824 
826 {
827  return fgDoubleFmt;
828 }
829 
830 ////////////////////////////////////////////////////////////////////////////////
831 /// convert float to string with configured format
832 
833 const char *TBufferText::ConvertFloat(Float_t value, char *buf, unsigned len, Bool_t not_optimize)
834 {
835  if (not_optimize) {
836  snprintf(buf, len, fgFloatFmt, value);
837  } else if ((value == std::nearbyint(value)) && (std::abs(value) < 1e15)) {
838  snprintf(buf, len, "%1.0f", value);
839  } else {
840  snprintf(buf, len, fgFloatFmt, value);
841  CompactFloatString(buf, len);
842  }
843  return buf;
844 }
845 
846 ////////////////////////////////////////////////////////////////////////////////
847 /// convert float to string with configured format
848 
849 const char *TBufferText::ConvertDouble(Double_t value, char *buf, unsigned len, Bool_t not_optimize)
850 {
851  if (not_optimize) {
852  snprintf(buf, len, fgFloatFmt, value);
853  } else if ((value == std::nearbyint(value)) && (std::abs(value) < 1e25)) {
854  snprintf(buf, len, "%1.0f", value);
855  } else {
856  snprintf(buf, len, fgDoubleFmt, value);
857  CompactFloatString(buf, len);
858  }
859  return buf;
860 }
TBufferText::GetFloatFormat
static const char * GetFloatFormat()
return current printf format for float members, default "%e"
Definition: TBufferText.cxx:806
TBufferText::SkipVersion
void SkipVersion(const TClass *cl=nullptr) final
Skip class version from I/O buffer.
Definition: TBufferText.cxx:675
n
const Int_t n
Definition: legend1.C:16
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TBufferText::SetByteCount
void SetByteCount(UInt_t, Bool_t=kFALSE) final
Definition: TBufferText.h:80
Version_t
short Version_t
Definition: RtypesCore.h:65
TBufferText::ReadFastArrayDouble32
void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=nullptr) final
read array of Double32_t from buffer
Definition: TBufferText.cxx:620
snprintf
#define snprintf
Definition: civetweb.c:1540
TObjArray
An array of TObjects.
Definition: TObjArray.h:37
TBuffer::ReadDouble
virtual void ReadDouble(Double_t &d)=0
f
#define f(i)
Definition: RSha256.hxx:104
TStreamerBase::WriteBuffer
Int_t WriteBuffer(TBuffer &b, char *pointer)
Write the base class into the buffer.
Definition: TStreamerElement.cxx:868
TBufferText::ReadStaticArrayFloat16
Int_t ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele=nullptr) final
Read array of Float16_t from buffer.
Definition: TBufferText.cxx:580
TStreamerInfo.h
TBuffer::WriteVersion
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
TBuffer::WriteFloat
virtual void WriteFloat(Float_t f)=0
TBuffer::fBufCur
char * fBufCur
Definition: TBuffer.h:52
TBufferText::SetDoubleFormat
static void SetDoubleFormat(const char *fmt="%.14e")
set printf format for double members, default "%.14e" use it after SetFloatFormat,...
Definition: TBufferText.cxx:815
TBuffer::ReadStaticArray
virtual Int_t ReadStaticArray(Bool_t *b)=0
TBuffer::ReadFastArray
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
TStreamerInfoActions.h
TBufferText::WriteArrayFloat16
void WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele=nullptr) final
Write array of Float16_t to buffer.
Definition: TBufferText.cxx:643
TBufferText::ApplySequenceVecPtr
Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection) final
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
Definition: TBufferText.cxx:102
TStreamerElement.h
TObject::Info
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:864
TObject::Error
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:890
TBufferText::WriteFastArrayDouble32
void WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=nullptr) final
Write array of Double32_t to buffer.
Definition: TBufferText.cxx:667
TBuffer::fBuffer
char * fBuffer
Definition: TBuffer.h:51
TBufferText::ReadFloat16
void ReadFloat16(Float_t *f, TStreamerElement *ele=nullptr) final
read a Float16_t from the buffer
Definition: TBufferText.cxx:488
exp
double exp(double)
TStreamerInfoActions::TActionSequence::fActions
ActionContainer_t fActions
Definition: TStreamerInfoActions.h:193
TStreamerInfo::BuildEmulated
void BuildEmulated(TFile *file)
Create an Emulation TStreamerInfo object.
Definition: TStreamerInfo.cxx:1251
Float_t
float Float_t
Definition: RtypesCore.h:57
TBuffer::kCannotHandleMemberWiseStreaming
@ kCannotHandleMemberWiseStreaming
Definition: TBuffer.h:76
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:162
TBufferText::ReadArrayDouble32
Int_t ReadArrayDouble32(Double_t *&d, TStreamerElement *ele=nullptr) override
Read array of Double32_t from buffer.
Definition: TBufferText.cxx:572
TBuffer::ReadFloat
virtual void ReadFloat(Float_t &f)=0
TBufferText::ReadDouble32
void ReadDouble32(Double_t *d, TStreamerElement *ele=nullptr) final
read a Double32_t from the buffer
Definition: TBufferText.cxx:496
TClass::GetClassVersion
Version_t GetClassVersion() const
Definition: TClass.h:390
TStreamerInfo::GetReadTextActions
TStreamerInfoActions::TActionSequence * GetReadTextActions()
Definition: TStreamerInfo.h:216
TBuffer::ReadArray
virtual Int_t ReadArray(Bool_t *&b)=0
TObjArray::UncheckedAt
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:90
TBufferText::~TBufferText
virtual ~TBufferText()
destructor
Definition: TBufferText.cxx:61
TBufferIO::TagStreamerInfo
void TagStreamerInfo(TVirtualStreamerInfo *info) override
Mark the classindex of the current file as using this TStreamerInfo.
Definition: TBufferIO.cxx:350
TBufferText::WriteFastArrayFloat16
void WriteFastArrayFloat16(const Float_t *d, Int_t n, TStreamerElement *ele=nullptr) final
Write array of Float16_t to buffer.
Definition: TBufferText.cxx:659
TFile.h
TStreamerInfo::Build
void Build(Bool_t isTransient=kFALSE)
Build the I/O data structure for the current class version.
Definition: TStreamerInfo.cxx:265
TBuffer::DecrementLevel
virtual void DecrementLevel(TVirtualStreamerInfo *)=0
TVirtualStreamerInfo
Abstract Interface class describing Streamer information for one class.
Definition: TVirtualStreamerInfo.h:37
bool
TBufferText::ReadClassBuffer
Int_t ReadClassBuffer(const TClass *, void *, const TClass *=nullptr) override
Deserialize information from a buffer into an object.
Definition: TBufferText.cxx:323
TBufferText
Base class for text-based streamers like TBufferJSON or TBufferXML Special actions list will use meth...
Definition: TBufferText.h:20
TBufferText::ReadFastArrayWithNbits
void ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits) final
read array of Float16_t from buffer
Definition: TBufferText.cxx:612
TStreamerInfo::Clear
void Clear(Option_t *)
If opt contains 'built', reset this StreamerInfo as if Build or BuildOld was never called on it (usef...
Definition: TStreamerInfo.cxx:2580
TBufferText::ApplySequence
Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object) final
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
Definition: TBufferText.cxx:69
TBuffer::Length
Int_t Length() const
Definition: TBuffer.h:100
TStreamerInfoActions::TActionSequence::fLoopConfig
TLoopConfiguration * fLoopConfig
If this is a bundle of memberwise streaming action, this configures the looping.
Definition: TStreamerInfoActions.h:192
TBufferText::WriteClassBuffer
Int_t WriteClassBuffer(const TClass *cl, void *pointer) override
Function called by the Streamer functions to serialize object at p to buffer b.
Definition: TBufferText.cxx:179
TStreamerInfoActions::TLoopConfiguration::GetFirstAddress
virtual void * GetFirstAddress(void *start, const void *end) const =0
TBuffer::EMode
EMode
Definition: TBuffer.h:73
gInterpreterMutex
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:44
TStreamerInfo
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:44
TBuffer::SetStreamerElementNumber
virtual void SetStreamerElementNumber(TStreamerElement *elem, Int_t comp_type)=0
TObject::SetBit
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
TBuffer::WriteFastArray
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
TBufferText::ReadArrayFloat16
Int_t ReadArrayFloat16(Float_t *&f, TStreamerElement *ele=nullptr) override
Read array of Float16_t from buffer.
Definition: TBufferText.cxx:564
TClass::GetConversionStreamerInfo
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition: TClass.cxx:6935
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TBufferText::ReadFastArrayWithFactor
void ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue) final
read array of Float16_t from buffer
Definition: TBufferText.cxx:604
gDebug
Int_t gDebug
Definition: TROOT.cxx:590
TClass::GetStreamerInfos
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:462
R__LOCKGUARD
#define R__LOCKGUARD(mutex)
Definition: TVirtualMutex.h:104
TClass::GetClass
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2938
TBufferText::TBufferText
TBufferText()
Default constructor.
Definition: TBufferText.cxx:43
TBuffer::GetParent
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:262
TVirtualStreamerInfo::IsCompiled
Bool_t IsCompiled() const
Definition: TVirtualStreamerInfo.h:156
TBufferText::fgFloatFmt
static const char * fgFloatFmt
! printf argument for floats, either "%f" or "%e" or "%10f" and so on
Definition: TBufferText.h:136
TVirtualMutex.h
TBuffer::ReadVersion
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
TBufferText::StreamObject
virtual void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=0)=0
TFile
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:54
TBufferText::ReadWithNbits
void ReadWithNbits(Float_t *ptr, Int_t nbits) final
Read a Float16_t from the buffer when the number of bits is specified (explicitly or not) see comment...
Definition: TBufferText.cxx:518
unsigned int
TBufferText::WriteDouble32
void WriteDouble32(Double_t *d, TStreamerElement *ele=nullptr) final
write a Double32_t to the buffer
Definition: TBufferText.cxx:556
TStreamerInfo::GetClassVersion
Int_t GetClassVersion() const
Definition: TStreamerInfo.h:208
TBufferIO
Direct subclass of TBuffer, implements common methods for TBufferFile and TBufferText classes.
Definition: TBufferIO.h:30
TClass::GetCurrentStreamerInfo
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition: TClass.h:409
TBuffer::WriteDouble
virtual void WriteDouble(Double_t d)=0
TClass::GetLastReadInfo
TVirtualStreamerInfo * GetLastReadInfo() const
Definition: TClass.h:414
TStreamerBase::ReadBuffer
Int_t ReadBuffer(TBuffer &b, char *pointer)
Read the content of the buffer.
Definition: TStreamerElement.cxx:772
TStreamerInfo::SetClassVersion
void SetClassVersion(Int_t vers)
Definition: TStreamerInfo.h:267
TBufferText::CompactFloatString
static void CompactFloatString(char *buf, unsigned len)
method compress float string, excluding exp and/or move float point
Definition: TBufferText.cxx:704
TBufferText.h
Double_t
double Double_t
Definition: RtypesCore.h:59
TBuffer::fBufSize
Int_t fBufSize
Definition: TBuffer.h:50
TClass::SetLastReadInfo
void SetLastReadInfo(TVirtualStreamerInfo *info)
Definition: TClass.h:415
TStreamerInfoActions::TActionSequence::fStreamerInfo
TVirtualStreamerInfo * fStreamerInfo
StreamerInfo used to derive these actions.
Definition: TStreamerInfoActions.h:191
TCollection::GetSize
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
TInterpreter.h
TClass
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
file
Definition: file.py:1
TBuffer::IncrementLevel
virtual void IncrementLevel(TVirtualStreamerInfo *info)=0
TBufferText::SetFloatFormat
static void SetFloatFormat(const char *fmt="%e")
set printf format for float/double members, default "%e" to change format only for doubles,...
Definition: TBufferText.cxx:795
TObject
Mother of all ROOT objects.
Definition: TObject.h:37
TCollection::Capacity
Int_t Capacity() const
Definition: TCollection.h:165
TBufferText::ConvertDouble
static const char * ConvertDouble(Double_t v, char *buf, unsigned len, Bool_t not_optimize=kFALSE)
convert float to string with configured format
Definition: TBufferText.cxx:849
TStreamerInfo::BuildOld
void BuildOld()
rebuild the TStreamerInfo structure
Definition: TStreamerInfo.cxx:1691
TBufferText::ReadBaseClass
virtual void ReadBaseClass(void *start, TStreamerBase *elem)
Read data of base class.
Definition: TBufferText.cxx:691
d
#define d(i)
Definition: RSha256.hxx:102
TStreamerInfo::GetWriteTextActions
TStreamerInfoActions::TActionSequence * GetWriteTextActions()
Definition: TStreamerInfo.h:219
TBuffer::WriteArray
virtual void WriteArray(const Bool_t *b, Int_t n)=0
TBufferText::WriteBaseClass
virtual void WriteBaseClass(void *start, TStreamerBase *elem)
Write data of base class.
Definition: TBufferText.cxx:683
TBufferText::WriteFloat16
void WriteFloat16(Float_t *f, TStreamerElement *ele=nullptr) final
write a Float16_t to the buffer
Definition: TBufferText.cxx:548
TBufferText::fgDoubleFmt
static const char * fgDoubleFmt
! printf argument for doubles, either "%f" or "%e" or "%10f" and so on
Definition: TBufferText.h:137
xmlio::cnt
const char * cnt
Definition: TXMLSetup.cxx:75
TBufferText::CheckByteCount
Int_t CheckByteCount(UInt_t, UInt_t, const TClass *) final
Definition: TBufferText.h:78
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TStreamerInfoActions::TActionSequence
Definition: TStreamerInfoActions.h:172
TVirtualStreamerInfo::IsRecovered
Int_t IsRecovered() const
Definition: TVirtualStreamerInfo.h:158
TBuffer::SetParent
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:270
Class
void Class()
Definition: Class.C:29
TBufferText::ReadWithFactor
void ReadWithFactor(Float_t *ptr, Double_t factor, Double_t minvalue) final
Read a Double32_t from the buffer when the factor and minimun value have been specified see comments ...
Definition: TBufferText.cxx:507
TBufferText::GetDoubleFormat
static const char * GetDoubleFormat()
return current printf format for double members, default "%.14e"
Definition: TBufferText.cxx:825
TStreamerInfoActions::TLoopConfiguration
Base class of the Configurations for the member wise looping routines.
Definition: TStreamerInfoActions.h:53
TStreamerElement
Definition: TStreamerElement.h:33
TStreamerBase
Definition: TStreamerElement.h:151
TBufferText::ReadStaticArrayDouble32
Int_t ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele=nullptr) final
Read array of Double32_t from buffer.
Definition: TBufferText.cxx:588
TBufferText::WriteArrayDouble32
void WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=nullptr) final
Write array of Double32_t to buffer.
Definition: TBufferText.cxx:651
TBufferText::ReadFastArrayFloat16
void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=nullptr) final
read array of Float16_t from buffer
Definition: TBufferText.cxx:596
TExMap.h
int
TBufferText::ConvertFloat
static const char * ConvertFloat(Float_t v, char *buf, unsigned len, Bool_t not_optimize=kFALSE)
convert float to string with configured format
Definition: TBufferText.cxx:833
TError.h