Logo ROOT   6.16/01
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
16Base class for text-based streamers like TBufferJSON or TBufferXML
17Special actions list will use methods, introduced in this class.
18
19Idea to have equivalent methods names in TBufferFile and TBufferText, that
20actions list for both are the same.
21*/
22
23#include "TBufferText.h"
24
25#include "TStreamerInfo.h"
26#include "TStreamerElement.h"
28#include "TFile.h"
29#include "TVirtualMutex.h"
30#include "TInterpreter.h"
31#include "TROOT.h"
32#include "TExMap.h"
33#include "TError.h"
36
37const char *TBufferText::fgFloatFmt = "%e";
38const 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
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
235Int_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
323Int_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 {
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
465void 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
473void 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
507void 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
529void 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{
662}
663
664////////////////////////////////////////////////////////////////////////////////
665/// Write array of Double32_t to buffer
666
668{
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
704void 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
795void 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
815void 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
833const 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
849const 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}
void Class()
Definition: Class.C:29
#define d(i)
Definition: RSha256.hxx:102
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
double exp(double)
#define R__LOCKGUARD(mutex)
#define snprintf
Definition: civetweb.c:1540
Direct subclass of TBuffer, implements common methods for TBufferFile and TBufferText classes.
Definition: TBufferIO.h:30
virtual void TagStreamerInfo(TVirtualStreamerInfo *info)
Mark the classindex of the current file as using this TStreamerInfo.
Definition: TBufferIO.cxx:350
Base class for text-based streamers like TBufferJSON or TBufferXML Special actions list will use meth...
Definition: TBufferText.h:21
virtual Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
Definition: TBufferText.cxx:69
static const char * ConvertFloat(Float_t v, char *buf, unsigned len, Bool_t not_optimize=kFALSE)
convert float to string with configured format
static const char * GetFloatFormat()
return current printf format for float members, default "%e"
virtual void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=nullptr)
stream object to/from buffer
virtual ~TBufferText()
destructor
Definition: TBufferText.cxx:61
virtual void ReadWithFactor(Float_t *ptr, Double_t factor, Double_t minvalue)
Read a Double32_t from the buffer when the factor and minimun value have been specified see comments ...
virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=nullptr)
read array of Double32_t from buffer
TBufferText()
Default constructor.
Definition: TBufferText.cxx:43
virtual void WriteFloat16(Float_t *f, TStreamerElement *ele=nullptr)
write a Float16_t to the buffer
virtual Int_t ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele=nullptr)
Read array of Double32_t from buffer.
static void CompactFloatString(char *buf, unsigned len)
method compress float string, excluding exp and/or move float point
virtual void SetByteCount(UInt_t, Bool_t=kFALSE)
Definition: TBufferText.h:81
virtual void WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=nullptr)
Write array of Double32_t to buffer.
virtual void WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=nullptr)
Write array of Double32_t to buffer.
virtual void ReadWithNbits(Float_t *ptr, Int_t nbits)
Read a Float16_t from the buffer when the number of bits is specified (explicitly or not) see comment...
virtual Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection)
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
static const char * ConvertDouble(Double_t v, char *buf, unsigned len, Bool_t not_optimize=kFALSE)
convert float to string with configured format
virtual void WriteDouble32(Double_t *d, TStreamerElement *ele=nullptr)
write a Double32_t to the buffer
virtual Int_t ReadArrayFloat16(Float_t *&f, TStreamerElement *ele=nullptr)
Read array of Float16_t from buffer.
virtual Int_t ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele=nullptr)
Read array of Float16_t from buffer.
virtual void ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits)
read array of Float16_t from buffer
virtual void ReadFloat16(Float_t *f, TStreamerElement *ele=nullptr)
read a Float16_t from the buffer
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)
Function called by the Streamer functions to serialize object at p to buffer b.
virtual void WriteBaseClass(void *start, TStreamerBase *elem)
Write data of base class.
virtual void SkipVersion(const TClass *cl=nullptr)
Skip class version from I/O buffer.
virtual void WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele=nullptr)
Write array of Float16_t to buffer.
virtual void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=nullptr)
read array of Float16_t from buffer
static const char * fgDoubleFmt
! printf argument for doubles, either "%f" or "%e" or "%10f" and so on
Definition: TBufferText.h:138
virtual void WriteFastArrayFloat16(const Float_t *d, Int_t n, TStreamerElement *ele=nullptr)
Write array of Float16_t to buffer.
virtual void ReadBaseClass(void *start, TStreamerBase *elem)
Read data of base class.
virtual Int_t ReadClassBuffer(const TClass *, void *, const TClass *=nullptr)
Deserialize information from a buffer into an object.
virtual void ReadDouble32(Double_t *d, TStreamerElement *ele=nullptr)
read a Double32_t from the buffer
static void SetFloatFormat(const char *fmt="%e")
set printf format for float/double members, default "%e" to change format only for doubles,...
virtual Int_t ReadArrayDouble32(Double_t *&d, TStreamerElement *ele=nullptr)
Read array of Double32_t from buffer.
static const char * GetDoubleFormat()
return current printf format for double members, default "%.14e"
virtual Int_t CheckByteCount(UInt_t, UInt_t, const TClass *)
Definition: TBufferText.h:79
virtual void ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue)
read array of Float16_t from buffer
static const char * fgFloatFmt
! printf argument for floats, either "%f" or "%e" or "%10f" and so on
Definition: TBufferText.h:137
static void SetDoubleFormat(const char *fmt="%.14e")
set printf format for double members, default "%.14e" use it after SetFloatFormat,...
virtual void ReadDouble(Double_t &d)=0
Int_t fBufSize
Definition: TBuffer.h:47
virtual void WriteDouble(Double_t d)=0
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:249
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:241
virtual void ReadFloat(Float_t &f)=0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
@ kCannotHandleMemberWiseStreaming
Definition: TBuffer.h:73
virtual void SetStreamerElementNumber(TStreamerElement *elem, Int_t comp_type)=0
virtual void WriteArray(const Bool_t *b, Int_t n)=0
virtual Int_t ReadArray(Bool_t *&b)=0
char * fBufCur
Definition: TBuffer.h:49
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void IncrementLevel(TVirtualStreamerInfo *info)=0
virtual void DecrementLevel(TVirtualStreamerInfo *)=0
char * fBuffer
Definition: TBuffer.h:48
virtual Int_t ReadStaticArray(Bool_t *b)=0
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual void WriteFloat(Float_t f)=0
Int_t Length() const
Definition: TBuffer.h:96
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition: TClass.h:410
void SetLastReadInfo(TVirtualStreamerInfo *info)
Definition: TClass.h:416
TVirtualStreamerInfo * GetLastReadInfo() const
Definition: TClass.h:415
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:462
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:6793
Version_t GetClassVersion() const
Definition: TClass.h:391
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:2885
Int_t Capacity() const
Definition: TCollection.h:165
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
Mother of all ROOT objects.
Definition: TObject.h:37
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Int_t WriteBuffer(TBuffer &b, char *pointer)
Write the base class into the buffer.
Int_t ReadBuffer(TBuffer &b, char *pointer)
Read the content of the buffer.
TLoopConfiguration * fLoopConfig
If this is a bundle of memberwise streaming action, this configures the looping.
TVirtualStreamerInfo * fStreamerInfo
StreamerInfo used to derive these actions.
Base class of the Configurations for the member wise looping routines.
virtual void * GetFirstAddress(void *start, const void *end) const =0
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
void SetClassVersion(Int_t vers)
void Clear(Option_t *)
If opt contains 'built', reset this StreamerInfo as if Build or BuildOld was never called on it (usef...
void Build()
Build the I/O data structure for the current class version.
TStreamerInfoActions::TActionSequence * GetReadTextActions()
TStreamerInfoActions::TActionSequence * GetWriteTextActions()
void BuildEmulated(TFile *file)
Create an Emulation TStreamerInfo object.
Int_t GetClassVersion() const
void BuildOld()
rebuild the TStreamerInfo structure
Abstract Interface class describing Streamer information for one class.
const Int_t n
Definition: legend1.C:16
static constexpr double s
Definition: file.py:1
const char * cnt
Definition: TXMLSetup.cxx:74