Logo ROOT   6.12/07
Reference Guide
TBufferJSON.cxx
Go to the documentation of this file.
1 //
2 // Author: Sergey Linev 4.03.2014
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, 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 TBufferJSON
14 \ingroup IO
15 
16 Class for serializing object into JavaScript Object Notation (JSON) format.
17 It creates such object representation, which can be directly
18 used in JavaScript ROOT (JSROOT) for drawing.
19 
20 TBufferJSON implements TBuffer interface, therefore most of
21 ROOT and user classes can be converted into JSON.
22 There are certain limitations for classes with custom streamers,
23 which should be equipped specially for this purposes (see TCanvas::Streamer()
24 as example).
25 
26 To perform conversion, one should use TBufferJSON::ConvertToJSON method like:
27 ~~~{.cpp}
28  TH1* h1 = new TH1I("h1","title",100, 0, 10);
29  h1->FillRandom("gaus",10000);
30  TString json = TBufferJSON::ConvertToJSON(h1);
31 ~~~
32 */
33 
34 #include "TBufferJSON.h"
35 
36 #include <typeinfo>
37 #include <string>
38 #include <string.h>
39 #include <locale.h>
40 
41 #include "Compression.h"
42 
43 #include "TArrayI.h"
44 #include "TObjArray.h"
45 #include "TROOT.h"
46 #include "TClass.h"
47 #include "TClassTable.h"
48 #include "TClassEdit.h"
49 #include "TDataType.h"
50 #include "TRealData.h"
51 #include "TDataMember.h"
52 #include "TMap.h"
53 #include "TExMap.h"
54 #include "TMethodCall.h"
55 #include "TStreamerInfo.h"
56 #include "TStreamerElement.h"
57 #include "TProcessID.h"
58 #include "TFile.h"
59 #include "TMemberStreamer.h"
60 #include "TStreamer.h"
61 #include "TStreamerInfoActions.h"
62 #include "RVersion.h"
63 #include "Riostream.h"
64 #include "RZip.h"
65 #include "TClonesArray.h"
66 #include "TVirtualMutex.h"
67 #include "TInterpreter.h"
68 
69 #ifdef R__VISUAL_CPLUSPLUS
70 #define FLong64 "%I64d"
71 #define FULong64 "%I64u"
72 #else
73 #define FLong64 "%lld"
74 #define FULong64 "%llu"
75 #endif
76 
78 
79 
80 const char *TBufferJSON::fgFloatFmt = "%e";
81 const char *TBufferJSON::fgDoubleFmt = "%.14e";
82 
83 // TArrayIndexProducer is used to correctly create
84 // JSON array separators for multi-dimensional JSON arrays
85 // It fully reproduces array dimensions as in original ROOT classes
86 // Contrary to binary I/O, which always writes flat arrays
87 
88 class TArrayIndexProducer {
89  protected:
90 
91  Int_t fTotalLen;
92  Int_t fCnt;
93  const char* fSepar;
94  TArrayI fIndicies;
95  TArrayI fMaxIndex;
96  TString fRes;
97  Bool_t fIsArray;
98 
99  public:
100  TArrayIndexProducer(TStreamerElement* elem, Int_t arraylen, const char* separ) :
101  fTotalLen(0),
102  fCnt(-1),
103  fSepar(separ),
104  fIndicies(),
105  fMaxIndex(),
106  fRes(),
107  fIsArray(kFALSE)
108  {
109  Bool_t usearrayindx = elem && (elem->GetArrayDim() > 0);
110  Bool_t isloop = elem && ((elem->GetType() == TStreamerInfo::kStreamLoop) ||
112  Bool_t usearraylen = (arraylen > (isloop ? 0 : 1));
113 
114  if (usearrayindx && (arraylen > 0)) {
115  if (isloop) {
116  usearrayindx = kFALSE;
117  usearraylen = kTRUE;
118  } else if (arraylen != elem->GetArrayLength()) {
119  printf("Problem with JSON coding of element %s type %d \n", elem->GetName(), elem->GetType());
120  }
121  }
122 
123  if (usearrayindx) {
124  fTotalLen = elem->GetArrayLength();
125  fMaxIndex.Set(elem->GetArrayDim());
126  for(int dim=0;dim<elem->GetArrayDim();dim++)
127  fMaxIndex[dim] = elem->GetMaxIndex(dim);
128  fIsArray = fTotalLen>1;
129  } else
130  if (usearraylen) {
131  fTotalLen = arraylen;
132  fMaxIndex.Set(1);
133  fMaxIndex[0] = arraylen;
134  fIsArray = kTRUE;
135  }
136 
137  if (fMaxIndex.GetSize() > 0) {
138  fIndicies.Set(fMaxIndex.GetSize());
139  fIndicies.Reset(0);
140  }
141  }
142 
143  TArrayIndexProducer(TDataMember* member, Int_t extradim, const char* separ) :
144  fTotalLen(0),
145  fCnt(-1),
146  fSepar(separ),
147  fIndicies(),
148  fMaxIndex(),
149  fRes(),
150  fIsArray(kFALSE)
151  {
152  Int_t ndim = member->GetArrayDim();
153  if (extradim > 0) ndim++;
154 
155  if (ndim > 0) {
156  fIndicies.Set(ndim);
157  fIndicies.Reset(0);
158  fMaxIndex.Set(ndim);
159  fTotalLen = 1;
160  for (int dim=0;dim<member->GetArrayDim();dim++) {
161  fMaxIndex[dim] = member->GetMaxIndex(dim);
162  fTotalLen *= member->GetMaxIndex(dim);
163  }
164 
165  if (extradim > 0) {
166  fMaxIndex[ndim-1] = extradim;
167  fTotalLen *= extradim;
168  }
169  }
170  fIsArray = fTotalLen>1;
171  }
172 
173  Int_t ReduceDimension()
174  {
175  // reduce one dimension of the array
176  // return size of reduced dimension
177  if (fMaxIndex.GetSize() == 0) return 0;
178  Int_t ndim = fMaxIndex.GetSize()-1;
179  Int_t len = fMaxIndex[ndim];
180  fMaxIndex.Set(ndim);
181  fIndicies.Set(ndim);
182  fTotalLen = fTotalLen/len;
183  fIsArray = fTotalLen>1;
184  return len;
185  }
186 
187 
188  Bool_t IsArray() const
189  {
190  return fIsArray;
191  }
192 
193  Bool_t IsDone() const
194  {
195  // return true when iteration over all arrays indexes are done
196  return !IsArray() || (fCnt >= fTotalLen);
197  }
198 
199  const char* GetBegin()
200  {
201  ++fCnt;
202  // return starting separator
203  fRes.Clear();
204  for (Int_t n=0;n<fIndicies.GetSize();++n) fRes.Append("[");
205  return fRes.Data();
206  }
207 
208  const char* GetEnd()
209  {
210  // return ending separator
211  fRes.Clear();
212  for (Int_t n=0;n<fIndicies.GetSize();++n) fRes.Append("]");
213  return fRes.Data();
214  }
215 
216  const char* NextSeparator()
217  {
218  // return intermediate or last separator
219 
220  if (++fCnt >= fTotalLen) return GetEnd();
221 
222  Int_t cnt = fIndicies.GetSize() - 1;
223  fIndicies[cnt]++;
224 
225  fRes.Clear();
226 
227  while ((cnt >= 0) && (cnt < fIndicies.GetSize())) {
228  if (fIndicies[cnt] >= fMaxIndex[cnt]) {
229  fRes.Append("]");
230  fIndicies[cnt--] = 0;
231  if (cnt >= 0) fIndicies[cnt]++;
232  continue;
233  }
234  fRes.Append(fIndicies[cnt] == 0 ? "[" : fSepar);
235  cnt++;
236  }
237  return fRes.Data();
238  }
239 
240 };
241 
242 
243 // TJSONStackObj is used to keep stack of object hierarchy,
244 // stored in TBuffer. For instance, data for parent class(es)
245 // stored in subnodes, but initial object node will be kept.
246 
247 class TJSONStackObj : public TObject {
248 public:
249  TStreamerInfo *fInfo; //!
250  TStreamerElement *fElem; //! element in streamer info
251  Bool_t fIsStreamerInfo; //!
252  Bool_t fIsElemOwner; //!
253  Bool_t fIsPostProcessed;//! indicate that value is written
254  Bool_t fIsObjStarted; //! indicate that object writing started, should be closed in postprocess
255  Bool_t fAccObjects; //! if true, accumulate whole objects in values
256  TObjArray fValues; //! raw values
257  Int_t fLevel; //! indent level
258  TArrayIndexProducer *fIndx; //! producer of ndim indexes
259 
260  TJSONStackObj() :
261  TObject(),
262  fInfo(0),
263  fElem(0),
264  fIsStreamerInfo(kFALSE),
265  fIsElemOwner(kFALSE),
266  fIsPostProcessed(kFALSE),
267  fIsObjStarted(kFALSE),
268  fAccObjects(kFALSE),
269  fValues(),
270  fLevel(0),
271  fIndx(0)
272  {
273  fValues.SetOwner(kTRUE);
274  }
275 
276  virtual ~TJSONStackObj()
277  {
278  if (fIsElemOwner) delete fElem;
279  if (fIndx) delete fIndx;
280  }
281 
282  Bool_t IsStreamerInfo() const
283  {
284  return fIsStreamerInfo;
285  }
286  Bool_t IsStreamerElement() const
287  {
288  return !fIsStreamerInfo && (fElem != 0);
289  }
290 
291  void PushValue(TString &v)
292  {
293  fValues.Add(new TObjString(v));
294  v.Clear();
295  }
296 };
297 
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// Creates buffer object to serialize data into json.
301 
303  TBuffer(TBuffer::kWrite),
304  fOutBuffer(),
305  fOutput(0),
306  fValue(),
307  fJsonrMap(),
308  fJsonrCnt(0),
309  fStack(),
310  fCompact(0),
311  fSemicolon(" : "),
312  fArraySepar(", "),
313  fNumericLocale()
314 {
315  fBufSize = 1000000000;
316 
317  SetParent(0);
319  //SetBit(kTextBasedStreaming);
320 
321  fOutBuffer.Capacity(10000);
322  fValue.Capacity(1000);
323  fOutput = &fOutBuffer;
324 
325  // checks if setlocale(LC_NUMERIC) returns others than "C"
326  // in this case locale will be changed and restored at the end of object conversion
327 
328  char* loc = setlocale(LC_NUMERIC, 0);
329  if ((loc!=0) && (strcmp(loc,"C")!=0)) {
330  fNumericLocale = loc;
331  setlocale(LC_NUMERIC, "C");
332  }
333 }
334 
335 ////////////////////////////////////////////////////////////////////////////////
336 /// destroy buffer
337 
339 {
340  fStack.Delete();
341 
342  if (fNumericLocale.Length()>0)
343  setlocale(LC_NUMERIC, fNumericLocale.Data());
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////////
347 /// Converts object, inherited from TObject class, to JSON string
348 /// Lower digit of compact parameter define formatting rules
349 /// - 0 - no any compression, human-readable form
350 /// - 1 - exclude spaces in the begin
351 /// - 2 - remove newlines
352 /// - 3 - exclude spaces as much as possible
353 ///
354 /// Second digit of compact parameter defines algorithm for arrays compression
355 /// - 0 - no compression, standard JSON array
356 /// - 1 - exclude leading, trailing zeros, required JSROOT v5
357 /// - 2 - check values repetition and empty gaps, required JSROOT v5
358 ///
359 /// Maximal compression achieved when compact parameter equal to 23
360 /// When member_name specified, converts only this data member
361 
362 TString TBufferJSON::ConvertToJSON(const TObject *obj, Int_t compact, const char *member_name)
363 {
364  TClass *clActual = 0;
365  void *ptr = (void *) obj;
366 
367  if (obj!=0) {
368  clActual = TObject::Class()->GetActualClass(obj);
369  if (!clActual) clActual = TObject::Class(); else
370  if (clActual != TObject::Class())
371  ptr = (void *) ((Long_t) obj - clActual->GetBaseClassOffset(TObject::Class()));
372  }
373 
374  return ConvertToJSON(ptr, clActual, compact, member_name);
375 }
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 // Set level of space/newline/array compression
379 // Lower digit of compact parameter define formatting rules
380 // - 0 - no any compression, human-readable form
381 // - 1 - exclude spaces in the begin
382 // - 2 - remove newlines
383 // - 3 - exclude spaces as much as possible
384 //
385 // Second digit of compact parameter defines algorithm for arrays compression
386 // - 0 - no compression, standard JSON array
387 // - 1 - exclude leading, trailing zeros, required JSROOT v5
388 // - 2 - check values repetition and empty gaps, required JSROOT v5
389 
390 void TBufferJSON::SetCompact(int level)
391 {
392  fCompact = level;
393  fSemicolon = (fCompact % 10 > 2) ? ":" : " : ";
394  fArraySepar = (fCompact % 10 > 2) ? "," : ", ";
395 }
396 
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 /// Converts any type of object to JSON string
400 /// One should provide pointer on object and its class name
401 /// Lower digit of compact parameter define formatting rules
402 /// - 0 - no any compression, human-readable form
403 /// - 1 - exclude spaces in the begin
404 /// - 2 - remove newlines
405 /// - 3 - exclude spaces as much as possible
406 ///
407 /// Second digit of compact parameter defines algorithm for arrays compression
408 /// - 0 - no compression, standard JSON array
409 /// - 1 - exclude leading, trailing zeros, required JSROOT v5
410 /// - 2 - check values repetition and empty gaps, required JSROOT v5
411 ///
412 /// Maximal compression achieved when compact parameter equal to 23
413 /// When member_name specified, converts only this data member
414 
415 TString TBufferJSON::ConvertToJSON(const void *obj, const TClass *cl,
416  Int_t compact, const char *member_name)
417 {
418  if ((member_name!=0) && (obj!=0)) {
419  TRealData *rdata = cl->GetRealData(member_name);
420  TDataMember *member = rdata ? rdata->GetDataMember() : 0;
421  if (member==0) {
422  TIter iter(cl->GetListOfRealData());
423  while ((rdata = dynamic_cast<TRealData*>(iter())) != 0) {
424  member = rdata->GetDataMember();
425  if (member && strcmp(member->GetName(), member_name)==0) break;
426  }
427  }
428  if (member==0) return TString();
429 
430  Int_t arraylen = -1;
431  if (member->GetArrayIndex()!=0) {
432  TRealData *idata = cl->GetRealData(member->GetArrayIndex());
433  TDataMember *imember = (idata!=0) ? idata->GetDataMember() : 0;
434  if ((imember!=0) && (strcmp(imember->GetTrueTypeName(),"int")==0)) {
435  arraylen = *((int *) ((char *) obj + idata->GetThisOffset()));
436  }
437  }
438 
439  void *ptr = (char *) obj + rdata->GetThisOffset();
440  if (member->IsaPointer()) ptr = *((char **) ptr);
441 
442  return TBufferJSON::ConvertToJSON(ptr, member, compact, arraylen);
443  }
444 
445  TBufferJSON buf;
446 
447  buf.SetCompact(compact);
448 
449  buf.JsonWriteObject(obj, cl);
450 
451  return buf.fOutBuffer.Length() ? buf.fOutBuffer : buf.fValue;
452 }
453 
454 ////////////////////////////////////////////////////////////////////////////////
455 /// Converts selected data member into json
456 /// Parameter ptr specifies address in memory, where data member is located
457 /// compact parameter defines compactness of produced JSON (from 0 to 3)
458 /// arraylen (when specified) is array length for this data member, //[fN] case
459 
461  Int_t compact, Int_t arraylen)
462 {
463  if ((ptr == 0) || (member == 0)) return TString("null");
464 
465  Bool_t stlstring = !strcmp(member->GetTrueTypeName(), "string");
466 
467  Int_t isstl = member->IsSTLContainer();
468 
469  TClass *mcl = member->IsBasic() ? 0 : gROOT->GetClass(member->GetTypeName());
470 
471  if ((mcl != 0) && (mcl != TString::Class()) && !stlstring && !isstl &&
472  (mcl->GetBaseClassOffset(TArray::Class()) != 0) && (arraylen<=0) && (member->GetArrayDim()==0))
473  return TBufferJSON::ConvertToJSON(ptr, mcl, compact);
474 
475  TBufferJSON buf;
476 
477  buf.SetCompact(compact);
478 
479  return buf.JsonWriteMember(ptr, member, mcl, arraylen);
480 }
481 
482 ////////////////////////////////////////////////////////////////////////////////
483 /// Convert object into JSON and store in text file
484 /// Returns size of the produce file
485 /// Used in TObject::SaveAs()
486 
487 Int_t TBufferJSON::ExportToFile(const char* filename, const TObject *obj, const char* option)
488 {
489  if (!obj || !filename || (*filename==0)) return 0;
490 
491  Int_t compact = strstr(filename,".json.gz") ? 3 : 0;
492  if (option && (*option >= '0') && (*option <='3')) compact = TString(option).Atoi();
493 
494  TString json = TBufferJSON::ConvertToJSON(obj, compact);
495 
496  std::ofstream ofs(filename);
497 
498  if (strstr(filename,".json.gz")) {
499  const char *objbuf = json.Data();
500  Long_t objlen = json.Length();
501 
502  unsigned long objcrc = R__crc32(0, NULL, 0);
503  objcrc = R__crc32(objcrc, (const unsigned char *) objbuf, objlen);
504 
505  // 10 bytes (ZIP header), compressed data, 8 bytes (CRC and original length)
506  Int_t buflen = 10 + objlen + 8;
507  if (buflen < 512) buflen = 512;
508 
509  char *buffer = (char *) malloc(buflen);
510  if (buffer == 0) return 0; // failure
511 
512  char *bufcur = buffer;
513 
514  *bufcur++ = 0x1f; // first byte of ZIP identifier
515  *bufcur++ = 0x8b; // second byte of ZIP identifier
516  *bufcur++ = 0x08; // compression method
517  *bufcur++ = 0x00; // FLAG - empty, no any file names
518  *bufcur++ = 0; // empty timestamp
519  *bufcur++ = 0; //
520  *bufcur++ = 0; //
521  *bufcur++ = 0; //
522  *bufcur++ = 0; // XFL (eXtra FLags)
523  *bufcur++ = 3; // OS 3 means Unix
524  //strcpy(bufcur, "item.json");
525  //bufcur += strlen("item.json")+1;
526 
527  char dummy[8];
528  memcpy(dummy, bufcur - 6, 6);
529 
530  // R__memcompress fills first 6 bytes with own header, therefore just overwrite them
531  unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, (char *) objbuf, objlen);
532 
533  memcpy(bufcur - 6, dummy, 6);
534 
535  bufcur += (ziplen - 6); // jump over compressed data (6 byte is extra ROOT header)
536 
537  *bufcur++ = objcrc & 0xff; // CRC32
538  *bufcur++ = (objcrc >> 8) & 0xff;
539  *bufcur++ = (objcrc >> 16) & 0xff;
540  *bufcur++ = (objcrc >> 24) & 0xff;
541 
542  *bufcur++ = objlen & 0xff; // original data length
543  *bufcur++ = (objlen >> 8) & 0xff; // original data length
544  *bufcur++ = (objlen >> 16) & 0xff; // original data length
545  *bufcur++ = (objlen >> 24) & 0xff; // original data length
546 
547  ofs.write(buffer, bufcur - buffer);
548 
549  free(buffer);
550  } else {
551  ofs << json.Data();
552  }
553 
554  ofs.close();
555 
556  return json.Length();
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// Convert object into JSON and store in text file
561 /// Returns size of the produce file
562 
563 Int_t TBufferJSON::ExportToFile(const char* filename, const void *obj, const TClass *cl, const char* option)
564 {
565  if (!obj || !cl || !filename || (*filename==0)) return 0;
566 
567  Int_t compact = strstr(filename,".json.gz") ? 3 : 0;
568  if (option && (*option >= '0') && (*option <='3')) compact = TString(option).Atoi();
569 
570  TString json = TBufferJSON::ConvertToJSON(obj, cl, compact);
571 
572  std::ofstream ofs (filename);
573 
574  if (strstr(filename,".json.gz")) {
575  const char *objbuf = json.Data();
576  Long_t objlen = json.Length();
577 
578  unsigned long objcrc = R__crc32(0, NULL, 0);
579  objcrc = R__crc32(objcrc, (const unsigned char *) objbuf, objlen);
580 
581  // 10 bytes (ZIP header), compressed data, 8 bytes (CRC and original length)
582  Int_t buflen = 10 + objlen + 8;
583  if (buflen < 512) buflen = 512;
584 
585  char *buffer = (char *) malloc(buflen);
586  if (buffer == 0) return 0; // failure
587 
588  char *bufcur = buffer;
589 
590  *bufcur++ = 0x1f; // first byte of ZIP identifier
591  *bufcur++ = 0x8b; // second byte of ZIP identifier
592  *bufcur++ = 0x08; // compression method
593  *bufcur++ = 0x00; // FLAG - empty, no any file names
594  *bufcur++ = 0; // empty timestamp
595  *bufcur++ = 0; //
596  *bufcur++ = 0; //
597  *bufcur++ = 0; //
598  *bufcur++ = 0; // XFL (eXtra FLags)
599  *bufcur++ = 3; // OS 3 means Unix
600  //strcpy(bufcur, "item.json");
601  //bufcur += strlen("item.json")+1;
602 
603  char dummy[8];
604  memcpy(dummy, bufcur - 6, 6);
605 
606  // R__memcompress fills first 6 bytes with own header, therefore just overwrite them
607  unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, (char *) objbuf, objlen);
608 
609  memcpy(bufcur - 6, dummy, 6);
610 
611  bufcur += (ziplen - 6); // jump over compressed data (6 byte is extra ROOT header)
612 
613  *bufcur++ = objcrc & 0xff; // CRC32
614  *bufcur++ = (objcrc >> 8) & 0xff;
615  *bufcur++ = (objcrc >> 16) & 0xff;
616  *bufcur++ = (objcrc >> 24) & 0xff;
617 
618  *bufcur++ = objlen & 0xff; // original data length
619  *bufcur++ = (objlen >> 8) & 0xff; // original data length
620  *bufcur++ = (objlen >> 16) & 0xff; // original data length
621  *bufcur++ = (objlen >> 24) & 0xff; // original data length
622 
623  ofs.write(buffer, bufcur - buffer);
624 
625  free(buffer);
626  } else {
627  ofs << json.Data();
628  }
629 
630  ofs.close();
631 
632  return json.Length();
633 }
634 
635 ////////////////////////////////////////////////////////////////////////////////
636 /// Convert single data member to JSON structures
637 /// Returns string with converted member
638 
640  TClass *memberClass, Int_t arraylen)
641 {
642  if (member == 0) return "null";
643 
644  if (gDebug > 2)
645  Info("JsonWriteMember", "Write member %s type %s ndim %d",
646  member->GetName(), member->GetTrueTypeName(), member->GetArrayDim());
647 
648  Int_t tid = member->GetDataType() ? member->GetDataType()->GetType() : kNoType_t;
649  if (strcmp(member->GetTrueTypeName(),"const char*")==0) tid = kCharStar; else
650  if (!member->IsBasic() || (tid == kOther_t) || (tid == kVoid_t)) tid = kNoType_t;
651 
652  if (ptr==0) return (tid == kCharStar) ? "\"\"" : "null";
653 
654  PushStack(0);
655  fValue.Clear();
656 
657  if (tid != kNoType_t) {
658 
659  TArrayIndexProducer indx(member, arraylen, fArraySepar.Data());
660 
661  Int_t shift = 1;
662 
663  if (indx.IsArray() && (tid==kChar_t))
664  shift = indx.ReduceDimension();
665 
666  char* ppp = (char*) ptr;
667 
668  if (indx.IsArray()) fOutBuffer.Append(indx.GetBegin());
669 
670  do {
671  fValue.Clear();
672 
673  switch (tid) {
674  case kChar_t:
675  if (shift>1)
676  JsonWriteConstChar((Char_t *)ppp, shift);
677  else
678  JsonWriteBasic(*((Char_t *)ppp));
679  break;
680  case kShort_t:
681  JsonWriteBasic(*((Short_t *)ppp));
682  break;
683  case kInt_t:
684  JsonWriteBasic(*((Int_t *)ppp));
685  break;
686  case kLong_t:
687  JsonWriteBasic(*((Long_t *)ppp));
688  break;
689  case kFloat_t:
690  JsonWriteBasic(*((Float_t *)ppp));
691  break;
692  case kCounter:
693  JsonWriteBasic(*((Int_t *)ppp));
694  break;
695  case kCharStar:
696  JsonWriteConstChar((Char_t *)ppp);
697  break;
698  case kDouble_t:
699  JsonWriteBasic(*((Double_t *)ppp));
700  break;
701  case kDouble32_t:
702  JsonWriteBasic(*((Double_t *)ppp));
703  break;
704  case kchar:
705  JsonWriteBasic(*((char *)ppp));
706  break;
707  case kUChar_t:
708  JsonWriteBasic(*((UChar_t *)ppp));
709  break;
710  case kUShort_t:
711  JsonWriteBasic(*((UShort_t *)ppp));
712  break;
713  case kUInt_t:
714  JsonWriteBasic(*((UInt_t *)ppp));
715  break;
716  case kULong_t:
717  JsonWriteBasic(*((ULong_t *)ppp));
718  break;
719  case kBits:
720  JsonWriteBasic(*((UInt_t *)ppp));
721  break;
722  case kLong64_t:
723  JsonWriteBasic(*((Long64_t *)ppp));
724  break;
725  case kULong64_t:
726  JsonWriteBasic(*((ULong64_t *)ppp));
727  break;
728  case kBool_t:
729  JsonWriteBasic(*((Bool_t *)ppp));
730  break;
731  case kFloat16_t:
732  JsonWriteBasic(*((Float_t *)ppp));
733  break;
734  case kOther_t:
735  case kVoid_t:
736  break;
737  }
738 
740  if (indx.IsArray()) fOutBuffer.Append(indx.NextSeparator());
741 
742  ppp += shift*member->GetUnitSize();
743 
744  } while (!indx.IsDone());
745 
746  fValue = fOutBuffer;
747 
748  } else if (memberClass == TString::Class()) {
749  TString *str = (TString *) ptr;
750  JsonWriteConstChar(str ? str->Data() : 0);
751  } else if ((member->IsSTLContainer() == ROOT::kSTLvector) ||
752  (member->IsSTLContainer() == ROOT::kSTLlist) ||
753  (member->IsSTLContainer() == ROOT::kSTLforwardlist)) {
754 
755  if (memberClass)
756  ((TClass *)memberClass)->Streamer((void *)ptr, *this);
757  else
758  fValue = "[]";
759 
760  if (fValue == "0") fValue = "[]";
761 
762  } else if (memberClass && memberClass->GetBaseClassOffset(TArray::Class()) == 0) {
763  TArray *arr = (TArray *) ptr;
764  if ((arr != 0) && (arr->GetSize() > 0)) {
765  arr->Streamer(*this);
766  // WriteFastArray(arr->GetArray(), arr->GetSize());
767  if (Stack()->fValues.GetLast() > 0) {
768  Warning("TBufferJSON", "When streaming TArray, more than 1 object in the stack, use second item");
769  fValue = Stack()->fValues.At(1)->GetName();
770  }
771  } else
772  fValue = "[]";
773  } else if (memberClass && !strcmp(memberClass->GetName(), "string")) {
774  // here value contains quotes, stack can be ignored
775  ((TClass *)memberClass)->Streamer((void *)ptr, *this);
776  }
777  PopStack();
778 
779  if (fValue.Length()) return fValue;
780 
781  if ((memberClass == 0) || (member->GetArrayDim() > 0) || (arraylen > 0)) return "<not supported>";
782 
783  return TBufferJSON::ConvertToJSON(ptr, memberClass);
784 }
785 
786 
787 ////////////////////////////////////////////////////////////////////////////////
788 /// Check that object already stored in the buffer
789 
791 {
792  if (obj == 0) return kTRUE;
793 
794  return fJsonrMap.find(obj) != fJsonrMap.end();
795 }
796 
797 ////////////////////////////////////////////////////////////////////////////////
798 /// Check that object already stored in the buffer
799 
800 Bool_t TBufferJSON::CheckObject(const void *ptr, const TClass * /*cl*/)
801 {
802  if (ptr == 0) return kTRUE;
803 
804  return fJsonrMap.find(ptr) != fJsonrMap.end();
805 }
806 
807 ////////////////////////////////////////////////////////////////////////////////
808 /// Convert object into json structures.
809 /// !!! Should be used only by TBufferJSON itself.
810 /// Use ConvertToJSON() methods to convert object to json
811 
812 void TBufferJSON::WriteObject(const TObject *obj, Bool_t cacheReuse /* = kTRUE */)
813 {
814  if (gDebug > 1)
815  Info("WriteObject", "Object %p", obj);
816 
817  WriteObjectAny(obj, TObject::Class(), cacheReuse);
818 }
819 
820 ////////////////////////////////////////////////////////////////////////////////
821 /// add new level to the structures stack
822 
823 TJSONStackObj *TBufferJSON::PushStack(Int_t inclevel)
824 {
825  TJSONStackObj *curr = Stack();
826  TJSONStackObj *stack = new TJSONStackObj();
827  stack->fLevel = (curr ? curr->fLevel : 0) + inclevel;
828  fStack.Add(stack);
829  return stack;
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 /// remove one level from stack
834 
835 TJSONStackObj *TBufferJSON::PopStack()
836 {
837  TObject *last = fStack.Last();
838  if (last != 0) {
839  fStack.Remove(last);
840  delete last;
841  fStack.Compress();
842  }
843  return dynamic_cast<TJSONStackObj *>(fStack.Last());
844 }
845 
846 ////////////////////////////////////////////////////////////////////////////////
847 /// return stack object of specified depth
848 
849 TJSONStackObj *TBufferJSON::Stack(Int_t depth)
850 {
851  TJSONStackObj *stack = 0;
852  if (depth <= fStack.GetLast())
853  stack = dynamic_cast<TJSONStackObj *>(fStack.At(fStack.GetLast() - depth));
854  return stack;
855 }
856 
857 ////////////////////////////////////////////////////////////////////////////////
858 /// Info("AppendOutput"," '%s' '%s'", line0, line1?line1 : "---");
859 
860 void TBufferJSON::AppendOutput(const char *line0, const char *line1)
861 {
862  if (line0 != 0) fOutput->Append(line0);
863 
864  if (line1 != 0) {
865  if (fCompact % 10 < 2) fOutput->Append("\n");
866 
867  if (strlen(line1) > 0) {
868  if (fCompact % 10 < 1) {
869  TJSONStackObj *stack = Stack();
870  if ((stack != 0) && (stack->fLevel > 0))
871  fOutput->Append(' ', stack->fLevel);
872  }
873  fOutput->Append(line1);
874  }
875  }
876 }
877 
878 ////////////////////////////////////////////////////////////////////////////////
879 
880 void TBufferJSON::JsonStartElement(const TStreamerElement *elem, const TClass *base_class)
881 {
882  const char *elem_name = 0;
883 
884  if (base_class == 0) {
885  elem_name = elem->GetName();
886  } else {
887  switch (JsonSpecialClass(base_class)) {
888  case TClassEdit::kVector :
889  elem_name = "fVector";
890  break;
891  case TClassEdit::kList :
892  elem_name = "fList";
893  break;
895  elem_name = "fForwardlist";
896  break;
897  case TClassEdit::kDeque :
898  elem_name = "fDeque";
899  break;
900  case TClassEdit::kMap :
901  elem_name = "fMap";
902  break;
903  case TClassEdit::kMultiMap :
904  elem_name = "fMultiMap";
905  break;
906  case TClassEdit::kSet :
907  elem_name = "fSet";
908  break;
909  case TClassEdit::kMultiSet :
910  elem_name = "fMultiSet";
911  break;
913  elem_name = "fUnorderedSet";
914  break;
916  elem_name = "fUnorderedMultiSet";
917  break;
919  elem_name = "fUnorderedMap";
920  break;
922  elem_name = "fUnorderedMultiMap";
923  break;
924  case TClassEdit::kBitSet :
925  elem_name = "fBitSet";
926  break;
927  case 100:
928  elem_name = "fArray";
929  break;
930  case 110:
931  case 120:
932  elem_name = "fString";
933  break;
934  }
935  }
936 
937  if (elem_name != 0) {
938  AppendOutput(",", "\"");
939  AppendOutput(elem_name);
940  AppendOutput("\"");
942  }
943 }
944 
945 ////////////////////////////////////////////////////////////////////////////////
946 
948 {
949  TJSONStackObj *stack = Stack();
950  if (stack != 0) stack->fIsPostProcessed = kTRUE;
951 }
952 
953 ////////////////////////////////////////////////////////////////////////////////
954 /// return non-zero value when class has special handling in JSON
955 /// it is TCollection (-130), TArray (100), TString (110), std::string (120) and STL containers (1..6)
956 
958 {
959  if (cl == 0) return 0;
960 
961  Bool_t isarray = strncmp("TArray", cl->GetName(), 6) == 0;
962  if (isarray) isarray = ((TClass *)cl)->GetBaseClassOffset(TArray::Class()) == 0;
963  if (isarray) return 100;
964 
965  // negative value used to indicate that collection stored as object
966  if (((TClass *)cl)->GetBaseClassOffset(TCollection::Class()) == 0) return -130;
967 
968  // special case for TString - it is saved as string in JSON
969  if (cl == TString::Class()) return 110;
970 
971  bool isstd = TClassEdit::IsStdClass(cl->GetName());
972  int isstlcont(ROOT::kNotSTL);
973  if (isstd) isstlcont = cl->GetCollectionType();
974  if (isstlcont > 0) return isstlcont;
975 
976  // also special handling for STL string, which handled similar to TString
977  if (isstd && !strcmp(cl->GetName(), "string")) return 120;
978 
979  return 0;
980 }
981 
982 ////////////////////////////////////////////////////////////////////////////////
983 /// Write object to buffer
984 /// If object was written before, only pointer will be stored
985 /// If check_map==kFALSE, object will be stored in any case and pointer will not be registered in the map
986 
987 void TBufferJSON::JsonWriteObject(const void *obj, const TClass *cl, Bool_t check_map)
988 {
989  // static int cnt = 0;
990 
991  if (!cl) obj = 0;
992 
993  //if (cnt++>100) return;
994 
995  if (gDebug > 0)
996  Info("JsonWriteObject", "Object %p class %s check_map %s", obj, cl ? cl->GetName() : "null", check_map ? "true" : "false");
997 
998  Int_t special_kind = JsonSpecialClass(cl);
999 
1000  TString fObjectOutput, *fPrevOutput(0);
1001 
1002  TJSONStackObj *stack = Stack();
1003 
1004  if (stack && stack->fAccObjects && ((fValue.Length() > 0) || (stack->fValues.GetLast() >= 0))) {
1005  // accumulate data of super-object in stack
1006 
1007  if (fValue.Length() > 0) {
1008  stack->fValues.Add(new TObjString(fValue));
1009  fValue.Clear();
1010  }
1011 
1012  // redirect output to local buffer, use it later as value
1013  fPrevOutput = fOutput;
1014  fOutput = &fObjectOutput;
1015  } else if ((special_kind <= 0) || (special_kind > 100)) {
1016  // FIXME: later post processing should be active for all special classes, while they all keep output in the value
1018  }
1019 
1020  if (obj == 0) {
1021  AppendOutput("null");
1022  goto post_process;
1023  }
1024 
1025  if (special_kind <= 0) {
1026  // add element name which should correspond to the object
1027  if (check_map) {
1028  std::map<const void *, unsigned>::const_iterator iter = fJsonrMap.find(obj);
1029  if (iter != fJsonrMap.end()) {
1030  // old-style refs, coded into string like "$ref12"
1031  // AppendOutput(Form("\"$ref:%u\"", iter->second));
1032  // new-style refs, coded into extra object {"$ref":12}, auto-detected by JSROOT 4.8 and higher
1033  AppendOutput(Form("{\"$ref\":%u}", iter->second));
1034  goto post_process;
1035  }
1036  fJsonrMap[obj] = fJsonrCnt;
1037  }
1038 
1039  fJsonrCnt++; // object counts is important in dereferencing part
1040 
1041  stack = PushStack(2);
1042  AppendOutput("{", "\"_typename\"");
1044  AppendOutput("\"");
1045  AppendOutput(cl->GetName());
1046  AppendOutput("\"");
1047  } else {
1048  // for array, string and STL collections different handling -
1049  // they not recognized at the end as objects in JSON
1050  stack = PushStack(0);
1051  }
1052 
1053  if (gDebug > 3)
1054  Info("JsonWriteObject", "Starting object %p write for class: %s",
1055  obj, cl->GetName());
1056 
1057  stack->fAccObjects = special_kind < 10;
1058 
1059  if (special_kind == -130)
1060  JsonStreamCollection((TCollection *) obj, cl);
1061  else
1062  ((TClass *)cl)->Streamer((void *)obj, *this);
1063 
1064  if (gDebug > 3)
1065  Info("JsonWriteObject", "Done object %p write for class: %s",
1066  obj, cl->GetName());
1067 
1068  if (special_kind == 100) {
1069  if (stack->fValues.GetLast() != 0)
1070  Error("JsonWriteObject", "Problem when writing array");
1071  stack->fValues.Delete();
1072  } else if ((special_kind == 110) || (special_kind == 120)) {
1073  if (stack->fValues.GetLast() > 1)
1074  Error("JsonWriteObject", "Problem when writing TString or std::string");
1075  stack->fValues.Delete();
1077  fValue.Clear();
1078  } else if ((special_kind > 0) && (special_kind <= TClassEdit::kBitSet)) {
1079  // here make STL container processing
1080 
1081  if (stack->fValues.GetLast() < 0) {
1082  // empty container
1083  if (fValue != "0") Error("JsonWriteObject", "With empty stack fValue!=0");
1084  fValue = "[]";
1085  } else {
1086 
1087  Int_t size = TString(stack->fValues.At(0)->GetName()).Atoi();
1088 
1089  if ((stack->fValues.GetLast() == 0) && ((size > 1) || (fValue.Index("[") == 0))) {
1090  // case of simple vector, array already in the value
1091  stack->fValues.Delete();
1092  if (fValue.Length() == 0) {
1093  Error("JsonWriteObject", "Empty value when it should contain something");
1094  fValue = "[]";
1095  }
1096 
1097  } else {
1098  const char *separ = "[";
1099 
1100  if (fValue.Length() > 0) {
1101  stack->fValues.Add(new TObjString(fValue));
1102  fValue.Clear();
1103  }
1104 
1105  if ((size * 2 == stack->fValues.GetLast()) &&
1106  ((special_kind == TClassEdit::kMap) || (special_kind == TClassEdit::kMultiMap) ||
1107  (special_kind == TClassEdit::kUnorderedMap) || (special_kind == TClassEdit::kUnorderedMultiMap))) {
1108  // special handling for std::map.
1109  // Create entries like { '$pair': 'typename' , 'first' : key, 'second' : value }
1110 
1111  TString pairtype = cl->GetName();
1112  if (pairtype.Index("multimap<") == 0)
1113  pairtype.Replace(0, 9, "pair<");
1114  else if (pairtype.Index("map<") == 0)
1115  pairtype.Replace(0, 4, "pair<");
1116  else
1117  pairtype = "TPair";
1118  pairtype = TString("\"") + pairtype + TString("\"");
1119  for (Int_t k = 1; k < stack->fValues.GetLast(); k += 2) {
1120  fValue.Append(separ);
1121  separ = fArraySepar.Data();
1122  // fJsonrCnt++; // do not add entry in the map, can conflict with objects inside values
1123  fValue.Append("{");
1124  fValue.Append("\"$pair\"");
1126  fValue.Append(pairtype.Data());
1128  fValue.Append("\"first\"");
1130  fValue.Append(stack->fValues.At(k)->GetName());
1132  fValue.Append("\"second\"");
1134  fValue.Append(stack->fValues.At(k + 1)->GetName());
1135  fValue.Append("}");
1136  }
1137  } else {
1138  // for most stl containers write just like blob, but skipping first element with size
1139  for (Int_t k = 1; k <= stack->fValues.GetLast(); k++) {
1140  fValue.Append(separ);
1141  separ = fArraySepar.Data();
1142  fValue.Append(stack->fValues.At(k)->GetName());
1143  }
1144  }
1145 
1146  fValue.Append("]");
1147  stack->fValues.Delete();
1148  }
1149  }
1150  }
1151 
1152  // reuse post-processing code for TObject or TRef
1153  PerformPostProcessing(stack, cl);
1154 
1155  if ((special_kind == 0) &&
1156  ((stack->fValues.GetLast() >= 0) || (fValue.Length() > 0))) {
1157  if (gDebug > 0)
1158  Info("JsonWriteObject", "Create blob value for class %s", cl->GetName());
1159 
1160  AppendOutput(fArraySepar.Data(), "\"_blob\"");
1162 
1163  const char *separ = "[";
1164 
1165  for (Int_t k = 0; k <= stack->fValues.GetLast(); k++) {
1166  AppendOutput(separ);
1167  separ = fArraySepar.Data();
1168  AppendOutput(stack->fValues.At(k)->GetName());
1169  }
1170 
1171  if (fValue.Length() > 0) {
1172  AppendOutput(separ);
1174  }
1175 
1176  AppendOutput("]");
1177 
1178  fValue.Clear();
1179  stack->fValues.Delete();
1180  }
1181 
1182  PopStack();
1183 
1184  if (special_kind <= 0) {
1185  AppendOutput(0, "}");
1186  }
1187 
1188 post_process:
1189 
1190  if (fPrevOutput != 0) {
1191  fOutput = fPrevOutput;
1192  // for STL containers and TArray object in fValue itself
1193  if ((special_kind <= 0) || (special_kind > 100))
1194  fValue = fObjectOutput;
1195  else if (fObjectOutput.Length() != 0)
1196  Error("JsonWriteObject", "Non-empty object output for special class %s", cl->GetName());
1197  }
1198 }
1199 
1200 ////////////////////////////////////////////////////////////////////////////////
1201 /// store content of collection
1202 
1204 {
1205  AppendOutput(",", "\"name\"");
1207  AppendOutput("\"");
1208  AppendOutput(col->GetName());
1209  AppendOutput("\",", "\"arr\"");
1211 
1212  // collection treated as JS Array
1213  AppendOutput("[");
1214 
1215  bool islist = col->InheritsFrom(TList::Class());
1216  TMap* map = 0;
1217  if (col->InheritsFrom(TMap::Class())) map = dynamic_cast<TMap*> (col);
1218 
1219  TString sopt;
1220  if (islist) { sopt.Capacity(500); sopt = "["; }
1221 
1222  TIter iter(col);
1223  TObject *obj;
1224  Bool_t first = kTRUE;
1225  while ((obj = iter()) != 0) {
1226  if (!first) AppendOutput(fArraySepar.Data());
1227 
1228  if (map) {
1229  // fJsonrCnt++; // do not account map pair as JSON object
1230  AppendOutput("{", "\"$pair\"");
1232  AppendOutput("\"TPair\"");
1233  AppendOutput(fArraySepar.Data(), "\"first\"");
1235  }
1236 
1238 
1239  if (map) {
1240  AppendOutput(fArraySepar.Data(), "\"second\"");
1242  WriteObjectAny(map->GetValue(obj), TObject::Class());
1243  AppendOutput("", "}");
1244  }
1245 
1246  if (islist) {
1247  if (!first) sopt.Append(fArraySepar.Data());
1248  sopt.Append("\"");
1249  sopt.Append(iter.GetOption());
1250  sopt.Append("\"");
1251  }
1252 
1253  first = kFALSE;
1254  }
1255 
1256  AppendOutput("]");
1257 
1258  if (islist) {
1259  sopt.Append("]");
1260  AppendOutput(",", "\"opt\"");
1262  AppendOutput(sopt.Data());
1263  }
1264  fValue.Clear();
1265 }
1266 
1267 
1268 ////////////////////////////////////////////////////////////////////////////////
1269 /// Function is called from TStreamerInfo WriteBuffer and ReadBuffer functions
1270 /// and indent new level in json structure.
1271 /// This call indicates, that TStreamerInfo functions starts streaming
1272 /// object data of correspondent class
1273 
1275 {
1276  if (gDebug > 2)
1277  Info("IncrementLevel", "Class: %s", (info ? info->GetClass()->GetName() : "custom"));
1278 
1279  WorkWithClass((TStreamerInfo *)info);
1280 }
1281 
1282 ////////////////////////////////////////////////////////////////////////////////
1283 /// Prepares buffer to stream data of specified class
1284 
1286 {
1287  if (sinfo != 0) cl = sinfo->GetClass();
1288 
1289  if (cl == 0) return;
1290 
1291  if (gDebug > 3) Info("WorkWithClass", "Class: %s", cl->GetName());
1292 
1293  TJSONStackObj *stack = Stack();
1294 
1295  if ((stack != 0) && stack->IsStreamerElement() && !stack->fIsObjStarted &&
1296  ((stack->fElem->GetType() == TStreamerInfo::kObject) ||
1297  (stack->fElem->GetType() == TStreamerInfo::kAny))) {
1298 
1299  stack->fIsObjStarted = kTRUE;
1300 
1301  fJsonrCnt++; // count object, but do not keep reference
1302 
1303  stack = PushStack(2);
1304  AppendOutput("{", "\"_typename\"");
1306  AppendOutput("\"");
1307  AppendOutput(cl->GetName());
1308  AppendOutput("\"");
1309  } else {
1310  stack = PushStack(0);
1311  }
1312 
1313  stack->fInfo = sinfo;
1314  stack->fIsStreamerInfo = kTRUE;
1315 }
1316 
1317 ////////////////////////////////////////////////////////////////////////////////
1318 /// Function is called from TStreamerInfo WriteBuffer and ReadBuffer functions
1319 /// and decrease level in json structure.
1320 
1322 {
1323  if (gDebug > 2)
1324  Info("DecrementLevel", "Class: %s",
1325  (info ? info->GetClass()->GetName() : "custom"));
1326 
1327  TJSONStackObj *stack = Stack();
1328 
1329  if (stack->IsStreamerElement()) {
1330  if (gDebug > 3)
1331  Info("DecrementLevel", " Perform post-processing elem: %s",
1332  stack->fElem->GetName());
1333 
1334  PerformPostProcessing(stack);
1335 
1336  stack = PopStack(); // remove stack of last element
1337  }
1338 
1339  if (stack->fInfo != (TStreamerInfo *) info)
1340  Error("DecrementLevel", " Mismatch of streamer info");
1341 
1342  PopStack(); // back from data of stack info
1343 
1344  if (gDebug > 3)
1345  Info("DecrementLevel", "Class: %s done",
1346  (info ? info->GetClass()->GetName() : "custom"));
1347 }
1348 
1349 ////////////////////////////////////////////////////////////////////////////////
1350 /// Function is called from TStreamerInfo WriteBuffer and Readbuffer functions
1351 /// and add/verify next element of json structure
1352 /// This calls allows separate data, correspondent to one class member, from another
1353 
1355 {
1356  if (gDebug > 3)
1357  Info("SetStreamerElementNumber", "Element name %s", elem->GetName());
1358 
1359  WorkWithElement(elem, comp_type);
1360 }
1361 
1362 ////////////////////////////////////////////////////////////////////////////////
1363 /// This is call-back from streamer which indicates
1364 /// that class member will be streamed
1365 /// Name of element used in JSON
1366 
1368 {
1369  TJSONStackObj *stack = Stack();
1370  if (stack == 0) {
1371  Error("WorkWithElement", "stack is empty");
1372  return;
1373  }
1374 
1375  if (gDebug > 0)
1376  Info("WorkWithElement", " Start element %s type %d typename %s",
1377  elem ? elem->GetName() : "---", elem ? elem->GetType() : -1, elem ? elem->GetTypeName() : "---");
1378 
1379  if (stack->IsStreamerElement()) {
1380  // this is post processing
1381 
1382  if (gDebug > 3)
1383  Info("WorkWithElement", " Perform post-processing elem: %s",
1384  stack->fElem->GetName());
1385 
1386  PerformPostProcessing(stack);
1387 
1388  stack = PopStack(); // go level back
1389  }
1390 
1391  fValue.Clear();
1392 
1393  if (stack == 0) {
1394  Error("WorkWithElement", "Lost of stack");
1395  return;
1396  }
1397 
1398  TStreamerInfo *info = stack->fInfo;
1399  if (!stack->IsStreamerInfo()) {
1400  Error("WorkWithElement", "Problem in Inc/Dec level");
1401  return;
1402  }
1403 
1404  Int_t number = info ? info->GetElements()->IndexOf(elem) : -1;
1405 
1406  if (elem == 0) {
1407  Error("WorkWithElement", "streamer info returns elem = 0");
1408  return;
1409  }
1410 
1411  TClass *base_class = elem->IsBase() ? elem->GetClassPointer() : 0;
1412 
1413  stack = PushStack(0);
1414  stack->fElem = (TStreamerElement *) elem;
1415  stack->fIsElemOwner = (number < 0);
1416 
1417  JsonStartElement(elem, base_class);
1418 
1420  (elem->GetArrayDim() > 0)) {
1421  stack->fIndx = new TArrayIndexProducer(elem, -1, fArraySepar.Data());
1422  AppendOutput(stack->fIndx->GetBegin());
1423  }
1424 }
1425 
1426 ////////////////////////////////////////////////////////////////////////////////
1427 /// Should be called in the beginning of custom class streamer.
1428 /// Informs buffer data about class which will be streamed now.
1429 ///
1430 /// ClassBegin(), ClassEnd() and ClassMember() should be used in
1431 /// custom class streamers to specify which kind of data are
1432 /// now streamed. Such information is used to correctly
1433 /// convert class data to JSON. Without that functions calls
1434 /// classes with custom streamers cannot be used with TBufferJSON
1435 
1437 {
1438  WorkWithClass(0, cl);
1439 }
1440 
1441 ////////////////////////////////////////////////////////////////////////////////
1442 /// Should be called at the end of custom streamer
1443 /// See TBufferJSON::ClassBegin for more details
1444 
1446 {
1447  DecrementLevel(0);
1448 }
1449 
1450 ////////////////////////////////////////////////////////////////////////////////
1451 /// Method indicates name and typename of class member,
1452 /// which should be now streamed in custom streamer
1453 /// Following combinations are supported:
1454 /// 1. name = "ClassName", typeName = 0 or typename==ClassName
1455 /// This is a case, when data of parent class "ClassName" should be streamed.
1456 /// For instance, if class directly inherited from TObject, custom
1457 /// streamer should include following code:
1458 /// ~~~{.cpp}
1459 /// b.ClassMember("TObject");
1460 /// TObject::Streamer(b);
1461 /// ~~~
1462 /// 2. Basic data type
1463 /// ~~~{.cpp}
1464 /// b.ClassMember("fInt","Int_t");
1465 /// b >> fInt;
1466 /// ~~~
1467 /// 3. Array of basic data types
1468 /// ~~~{.cpp}
1469 /// b.ClassMember("fArr","Int_t", 5);
1470 /// b.ReadFastArray(fArr, 5);
1471 /// ~~~
1472 /// 4. Object as data member
1473 /// ~~~{.cpp}
1474 /// b.ClassMember("fName","TString");
1475 /// fName.Streamer(b);
1476 /// ~~~
1477 /// 5. Pointer on object as data member
1478 /// ~~~{.cpp}
1479 /// b.ClassMember("fObj","TObject*");
1480 /// b.StreamObject(fObj);
1481 /// ~~~
1482 ///
1483 /// arrsize1 and arrsize2 arguments (when specified) indicate first and
1484 /// second dimension of array. Can be used for array of basic types.
1485 /// See ClassBegin() method for more details.
1486 
1487 void TBufferJSON::ClassMember(const char *name, const char *typeName,
1488  Int_t arrsize1, Int_t arrsize2)
1489 {
1490  if (typeName == 0) typeName = name;
1491 
1492  if ((name == 0) || (strlen(name) == 0)) {
1493  Error("ClassMember", "Invalid member name");
1494  return;
1495  }
1496 
1497  TString tname = typeName;
1498 
1499  Int_t typ_id = -1;
1500 
1501  if (strcmp(typeName, "raw:data") == 0)
1502  typ_id = TStreamerInfo::kMissing;
1503 
1504  if (typ_id < 0) {
1505  TDataType *dt = gROOT->GetType(typeName);
1506  if (dt != 0)
1507  if ((dt->GetType() > 0) && (dt->GetType() < 20))
1508  typ_id = dt->GetType();
1509  }
1510 
1511  if (typ_id < 0)
1512  if (strcmp(name, typeName) == 0) {
1513  TClass *cl = TClass::GetClass(tname.Data());
1514  if (cl != 0) typ_id = TStreamerInfo::kBase;
1515  }
1516 
1517  if (typ_id < 0) {
1518  Bool_t isptr = kFALSE;
1519  if (tname[tname.Length() - 1] == '*') {
1520  tname.Resize(tname.Length() - 1);
1521  isptr = kTRUE;
1522  }
1523  TClass *cl = TClass::GetClass(tname.Data());
1524  if (cl == 0) {
1525  Error("ClassMember", "Invalid class specifier %s", typeName);
1526  return;
1527  }
1528 
1529  if (cl->IsTObject())
1531  else
1532  typ_id = isptr ? TStreamerInfo::kAnyp : TStreamerInfo::kAny;
1533 
1534  if ((cl == TString::Class()) && !isptr)
1535  typ_id = TStreamerInfo::kTString;
1536  }
1537 
1538  TStreamerElement *elem = 0;
1539 
1540  if (typ_id == TStreamerInfo::kMissing) {
1541  elem = new TStreamerElement(name, "title", 0, typ_id, "raw:data");
1542  } else if (typ_id == TStreamerInfo::kBase) {
1543  TClass *cl = TClass::GetClass(tname.Data());
1544  if (cl != 0) {
1545  TStreamerBase *b = new TStreamerBase(tname.Data(), "title", 0);
1546  b->SetBaseVersion(cl->GetClassVersion());
1547  elem = b;
1548  }
1549  } else if ((typ_id > 0) && (typ_id < 20)) {
1550  elem = new TStreamerBasicType(name, "title", 0, typ_id, typeName);
1551  } else if ((typ_id == TStreamerInfo::kObject) ||
1552  (typ_id == TStreamerInfo::kTObject) ||
1553  (typ_id == TStreamerInfo::kTNamed)) {
1554  elem = new TStreamerObject(name, "title", 0, tname.Data());
1555  } else if (typ_id == TStreamerInfo::kObjectp) {
1556  elem = new TStreamerObjectPointer(name, "title", 0, tname.Data());
1557  } else if (typ_id == TStreamerInfo::kAny) {
1558  elem = new TStreamerObjectAny(name, "title", 0, tname.Data());
1559  } else if (typ_id == TStreamerInfo::kAnyp) {
1560  elem = new TStreamerObjectAnyPointer(name, "title", 0, tname.Data());
1561  } else if (typ_id == TStreamerInfo::kTString) {
1562  elem = new TStreamerString(name, "title", 0);
1563  }
1564 
1565  if (elem == 0) {
1566  Error("ClassMember", "Invalid combination name = %s type = %s",
1567  name, typeName);
1568  return;
1569  }
1570 
1571  if (arrsize1 > 0) {
1572  elem->SetArrayDim(arrsize2 > 0 ? 2 : 1);
1573  elem->SetMaxIndex(0, arrsize1);
1574  if (arrsize2 > 0)
1575  elem->SetMaxIndex(1, arrsize2);
1576  }
1577 
1578  // we indicate that there is no streamerinfo
1579  WorkWithElement(elem, -1);
1580 }
1581 
1582 ////////////////////////////////////////////////////////////////////////////////
1583 /// Function is converts TObject and TString structures to more compact representation
1584 
1585 void TBufferJSON::PerformPostProcessing(TJSONStackObj *stack, const TClass *obj_cl)
1586 {
1587  if (stack->fIsPostProcessed) return;
1588 
1589  const TStreamerElement *elem = stack->fElem;
1590 
1591  if (!elem && !obj_cl) return;
1592 
1593  stack->fIsPostProcessed = kTRUE;
1594 
1595  // when element was written as separate object, close only braces and exit
1596  if (stack->fIsObjStarted) {
1597  AppendOutput("", "}");
1598  return;
1599  }
1600 
1601  Bool_t isTObject(kFALSE), isTRef(kFALSE), isTString(kFALSE), isSTLstring(kFALSE), isOffsetPArray(kFALSE), isTArray(kFALSE);
1602 
1603  if (obj_cl) {
1604  if (obj_cl == TObject::Class()) isTObject = kTRUE;
1605  else if (obj_cl == TRef::Class()) isTRef = kTRUE;
1606  else return;
1607  } else {
1608  const char *typname = elem->IsBase() ? elem->GetName() : elem->GetTypeName();
1609  isTObject = (elem->GetType() == TStreamerInfo::kTObject) || (strcmp("TObject", typname) == 0);
1610  isTString = elem->GetType() == TStreamerInfo::kTString;
1611  isSTLstring = elem->GetType() == TStreamerInfo::kSTLstring;
1612  isOffsetPArray = (elem->GetType() > TStreamerInfo::kOffsetP) && (elem->GetType() < TStreamerInfo::kOffsetP + 20);
1613  isTArray = (strncmp("TArray", typname, 6) == 0);
1614  }
1615 
1616  if (isTString || isSTLstring) {
1617  // just remove all kind of string length information
1618 
1619  if (gDebug > 3)
1620  Info("PerformPostProcessing", "reformat string value = '%s'", fValue.Data());
1621 
1622  stack->fValues.Delete();
1623  } else if (isOffsetPArray) {
1624  // basic array with [fN] comment
1625 
1626  if ((stack->fValues.GetLast() < 0) && (fValue == "0")) {
1627  fValue = "[]";
1628  } else if ((stack->fValues.GetLast() == 0) &&
1629  (strcmp(stack->fValues.Last()->GetName(), "1") == 0)) {
1630  stack->fValues.Delete();
1631  } else {
1632  Error("PerformPostProcessing", "Wrong values for kOffsetP element %s",
1633  (elem ? elem->GetName() : "---"));
1634  stack->fValues.Delete();
1635  fValue = "[]";
1636  }
1637  } else if (isTObject || isTRef) {
1638  // complex workaround for TObject/TRef streamer
1639  // would be nice if other solution can be found
1640  // Here is not supported TRef on TRef (double reference)
1641 
1642  Int_t cnt = stack->fValues.GetLast()+1;
1643  if (fValue.Length() > 0) cnt++;
1644 
1645  if (cnt<2 || cnt>3) {
1646  if (gDebug > 0)
1647  Error("PerformPostProcessing", "When storing TObject/TRef, strange number of items %d", cnt);
1648  AppendOutput(",", "\"dummy\"");
1650  } else {
1651  AppendOutput(",", "\"fUniqueID\"");
1653  AppendOutput(stack->fValues.At(0)->GetName());
1654  AppendOutput(",", "\"fBits\"");
1656  AppendOutput((stack->fValues.GetLast()>0) ? stack->fValues.At(1)->GetName() : fValue.Data());
1657  if (cnt==3) {
1658  AppendOutput(",", "\"fPID\"");
1660  AppendOutput((stack->fValues.GetLast()>1) ? stack->fValues.At(2)->GetName() : fValue.Data());
1661  }
1662 
1663  stack->fValues.Delete();
1664  fValue.Clear();
1665  return;
1666  }
1667 
1668  } else if (isTArray) {
1669  // for TArray one deletes complete stack
1670  stack->fValues.Delete();
1671  }
1672 
1673  if (elem && elem->IsBase() && (fValue.Length() == 0)) {
1674  // here base class data already completely stored
1675  return;
1676  }
1677 
1678  if (stack->fValues.GetLast() >= 0) {
1679  // append element blob data just as abstract array, user is responsible to decode it
1680  AppendOutput("[");
1681  for (Int_t n = 0; n <= stack->fValues.GetLast(); n++) {
1682  AppendOutput(stack->fValues.At(n)->GetName());
1684  }
1685  }
1686 
1687  if (fValue.Length() == 0) {
1688  AppendOutput("null");
1689  } else {
1691  fValue.Clear();
1692  }
1693 
1694  if (stack->fValues.GetLast() >= 0)
1695  AppendOutput("]");
1696 }
1697 
1698 ////////////////////////////////////////////////////////////////////////////////
1699 /// suppressed function of TBuffer
1700 
1702 {
1703  return 0;
1704 }
1705 
1706 ////////////////////////////////////////////////////////////////////////////////
1707 /// suppressed function of TBuffer
1708 
1710 {
1711 }
1712 
1713 ////////////////////////////////////////////////////////////////////////////////
1714 /// suppressed function of TBuffer
1715 
1717  const TClass * /*cl*/)
1718 {
1719  return 0;
1720 }
1721 
1722 ////////////////////////////////////////////////////////////////////////////////
1723 /// suppressed function of TBuffer
1724 
1726 {
1727  return 0;
1728 }
1729 
1730 ////////////////////////////////////////////////////////////////////////////////
1731 /// suppressed function of TBuffer
1732 
1734 {
1735 }
1736 
1737 ////////////////////////////////////////////////////////////////////////////////
1738 /// Skip class version from I/O buffer.
1739 
1741 {
1742  ReadVersion(0, 0, cl);
1743 }
1744 
1745 ////////////////////////////////////////////////////////////////////////////////
1746 /// read version value from buffer
1747 
1749  const TClass * /*cl*/)
1750 {
1751  Version_t res = 0;
1752 
1753  if (start) *start = 0;
1754  if (bcnt) *bcnt = 0;
1755 
1756  if (gDebug > 3) Info("ReadVersion", "Version = %d", res);
1757 
1758  return res;
1759 }
1760 
1761 ////////////////////////////////////////////////////////////////////////////////
1762 /// Ignored in TBufferJSON
1763 
1764 UInt_t TBufferJSON::WriteVersion(const TClass * /*cl*/, Bool_t /* useBcnt */)
1765 {
1766  return 0;
1767 }
1768 
1769 ////////////////////////////////////////////////////////////////////////////////
1770 /// Read object from buffer. Only used from TBuffer
1771 
1773 {
1774  return 0;
1775 }
1776 
1777 ////////////////////////////////////////////////////////////////////////////////
1778 /// Skip any kind of object from buffer
1779 
1781 {
1782 }
1783 
1784 ////////////////////////////////////////////////////////////////////////////////
1785 /// Write object to buffer. Only used from TBuffer
1786 
1787 void TBufferJSON::WriteObjectClass(const void *actualObjStart,
1788  const TClass *actualClass,
1789  Bool_t cacheReuse)
1790 {
1791  if (gDebug > 3)
1792  Info("WriteObjectClass", "Class %s", (actualClass ? actualClass->GetName() : " null"));
1793 
1794  JsonWriteObject(actualObjStart, actualClass, cacheReuse);
1795 }
1796 
1797 #define TJSONPushValue() \
1798  if (fValue.Length() > 0) Stack()->PushValue(fValue);
1799 
1800 
1801 // macro to read array, which include size attribute
1802 #define TBufferJSON_ReadArray(tname, vname) \
1803  { \
1804  if (!vname) return 0; \
1805  return 1; \
1806  }
1807 
1808 ////////////////////////////////////////////////////////////////////////////////
1809 /// read a Float16_t from the buffer
1810 
1812 {
1813 }
1814 
1815 ////////////////////////////////////////////////////////////////////////////////
1816 /// read a Double32_t from the buffer
1817 
1819 {
1820 }
1821 
1822 ////////////////////////////////////////////////////////////////////////////////
1823 /// Read a Double32_t from the buffer when the factor and minimun value have
1824 /// been specified
1825 /// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
1826 /// Currently TBufferJSON does not optimize space in this case.
1827 
1829  Double_t /* minvalue */)
1830 {
1831 }
1832 
1833 ////////////////////////////////////////////////////////////////////////////////
1834 /// Read a Float16_t from the buffer when the number of bits is specified
1835 /// (explicitly or not)
1836 /// see comments about Float16_t encoding at TBufferFile::WriteFloat16().
1837 /// Currently TBufferJSON does not optimize space in this case.
1838 
1840 {
1841 }
1842 
1843 ////////////////////////////////////////////////////////////////////////////////
1844 /// Read a Double32_t from the buffer when the factor and minimun value have
1845 /// been specified
1846 /// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
1847 /// Currently TBufferJSON does not optimize space in this case.
1848 
1850  Double_t /* minvalue */)
1851 {
1852 }
1853 
1854 ////////////////////////////////////////////////////////////////////////////////
1855 /// Read a Double32_t from the buffer when the number of bits is specified
1856 /// (explicitly or not)
1857 /// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
1858 /// Currently TBufferJSON does not optimize space in this case.
1859 
1861 {
1862 }
1863 
1864 ////////////////////////////////////////////////////////////////////////////////
1865 /// write a Float16_t to the buffer
1866 
1868 {
1869  TJSONPushValue();
1870 
1871  JsonWriteBasic(*f);
1872 }
1873 
1874 ////////////////////////////////////////////////////////////////////////////////
1875 /// write a Double32_t to the buffer
1876 
1878 {
1879  TJSONPushValue();
1880 
1881  JsonWriteBasic(*d);
1882 }
1883 
1884 ////////////////////////////////////////////////////////////////////////////////
1885 /// Read array of Bool_t from buffer
1886 
1888 {
1890 }
1891 
1892 ////////////////////////////////////////////////////////////////////////////////
1893 /// Read array of Char_t from buffer
1894 
1896 {
1898 }
1899 
1900 ////////////////////////////////////////////////////////////////////////////////
1901 /// Read array of UChar_t from buffer
1902 
1904 {
1906 }
1907 
1908 ////////////////////////////////////////////////////////////////////////////////
1909 /// Read array of Short_t from buffer
1910 
1912 {
1914 }
1915 
1916 ////////////////////////////////////////////////////////////////////////////////
1917 /// Read array of UShort_t from buffer
1918 
1920 {
1922 }
1923 
1924 ////////////////////////////////////////////////////////////////////////////////
1925 /// Read array of Int_t from buffer
1926 
1928 {
1930 }
1931 
1932 ////////////////////////////////////////////////////////////////////////////////
1933 /// Read array of UInt_t from buffer
1934 
1936 {
1938 }
1939 
1940 ////////////////////////////////////////////////////////////////////////////////
1941 /// Read array of Long_t from buffer
1942 
1944 {
1946 }
1947 
1948 ////////////////////////////////////////////////////////////////////////////////
1949 /// Read array of ULong_t from buffer
1950 
1952 {
1954 }
1955 
1956 ////////////////////////////////////////////////////////////////////////////////
1957 /// Read array of Long64_t from buffer
1958 
1960 {
1962 }
1963 
1964 ////////////////////////////////////////////////////////////////////////////////
1965 /// Read array of ULong64_t from buffer
1966 
1968 {
1970 }
1971 
1972 ////////////////////////////////////////////////////////////////////////////////
1973 /// Read array of Float_t from buffer
1974 
1976 {
1978 }
1979 
1980 ////////////////////////////////////////////////////////////////////////////////
1981 /// Read array of Double_t from buffer
1982 
1984 {
1986 }
1987 
1988 ////////////////////////////////////////////////////////////////////////////////
1989 /// Read array of Float16_t from buffer
1990 
1992 {
1994 }
1995 
1996 ////////////////////////////////////////////////////////////////////////////////
1997 /// Read array of Double32_t from buffer
1998 
2000 {
2002 }
2003 
2004 // dummy macro to read array from json buffer
2005 #define TBufferJSON_ReadStaticArray(vname) \
2006  { \
2007  if (!vname) return 0; \
2008  return 1; \
2009  }
2010 
2011 ////////////////////////////////////////////////////////////////////////////////
2012 /// Read array of Bool_t from buffer
2013 
2015 {
2017 }
2018 
2019 ////////////////////////////////////////////////////////////////////////////////
2020 /// Read array of Char_t from buffer
2021 
2023 {
2025 }
2026 
2027 ////////////////////////////////////////////////////////////////////////////////
2028 /// Read array of UChar_t from buffer
2029 
2031 {
2033 }
2034 
2035 ////////////////////////////////////////////////////////////////////////////////
2036 /// Read array of Short_t from buffer
2037 
2039 {
2041 }
2042 
2043 ////////////////////////////////////////////////////////////////////////////////
2044 /// Read array of UShort_t from buffer
2045 
2047 {
2049 }
2050 
2051 ////////////////////////////////////////////////////////////////////////////////
2052 /// Read array of Int_t from buffer
2053 
2055 {
2057 }
2058 
2059 ////////////////////////////////////////////////////////////////////////////////
2060 /// Read array of UInt_t from buffer
2061 
2063 {
2065 }
2066 
2067 ////////////////////////////////////////////////////////////////////////////////
2068 /// Read array of Long_t from buffer
2069 
2071 {
2073 }
2074 
2075 ////////////////////////////////////////////////////////////////////////////////
2076 /// Read array of ULong_t from buffer
2077 
2079 {
2081 }
2082 
2083 ////////////////////////////////////////////////////////////////////////////////
2084 /// Read array of Long64_t from buffer
2085 
2087 {
2089 }
2090 
2091 ////////////////////////////////////////////////////////////////////////////////
2092 /// Read array of ULong64_t from buffer
2093 
2095 {
2097 }
2098 
2099 ////////////////////////////////////////////////////////////////////////////////
2100 /// Read array of Float_t from buffer
2101 
2103 {
2105 }
2106 
2107 ////////////////////////////////////////////////////////////////////////////////
2108 /// Read array of Double_t from buffer
2109 
2111 {
2113 }
2114 
2115 ////////////////////////////////////////////////////////////////////////////////
2116 /// Read array of Float16_t from buffer
2117 
2119 {
2121 }
2122 
2123 ////////////////////////////////////////////////////////////////////////////////
2124 /// Read array of Double32_t from buffer
2125 
2127 {
2129 }
2130 
2131 // macro to read content of array, which not include size of array
2132 // macro also treat situation, when instead of one single array chain
2133 // of several elements should be produced
2134 #define TBufferJSON_ReadFastArray(vname) \
2135  { \
2136  if (n <= 0) return; \
2137  if (!vname) return; \
2138  }
2139 
2140 ////////////////////////////////////////////////////////////////////////////////
2141 /// read array of Bool_t from buffer
2142 
2144 {
2146 }
2147 
2148 ////////////////////////////////////////////////////////////////////////////////
2149 /// read array of Char_t from buffer
2150 
2152 {
2154 }
2155 
2156 ////////////////////////////////////////////////////////////////////////////////
2157 /// read array of Char_t from buffer
2158 
2160 {
2162 }
2163 
2164 ////////////////////////////////////////////////////////////////////////////////
2165 /// read array of UChar_t from buffer
2166 
2168 {
2170 }
2171 
2172 ////////////////////////////////////////////////////////////////////////////////
2173 /// read array of Short_t from buffer
2174 
2176 {
2178 }
2179 
2180 ////////////////////////////////////////////////////////////////////////////////
2181 /// read array of UShort_t from buffer
2182 
2184 {
2186 }
2187 
2188 ////////////////////////////////////////////////////////////////////////////////
2189 /// read array of Int_t from buffer
2190 
2192 {
2194 }
2195 
2196 ////////////////////////////////////////////////////////////////////////////////
2197 /// read array of UInt_t from buffer
2198 
2200 {
2202 }
2203 
2204 ////////////////////////////////////////////////////////////////////////////////
2205 /// read array of Long_t from buffer
2206 
2208 {
2210 }
2211 
2212 ////////////////////////////////////////////////////////////////////////////////
2213 /// read array of ULong_t from buffer
2214 
2216 {
2218 }
2219 
2220 ////////////////////////////////////////////////////////////////////////////////
2221 /// read array of Long64_t from buffer
2222 
2224 {
2226 }
2227 
2228 ////////////////////////////////////////////////////////////////////////////////
2229 /// read array of ULong64_t from buffer
2230 
2232 {
2234 }
2235 
2236 ////////////////////////////////////////////////////////////////////////////////
2237 /// read array of Float_t from buffer
2238 
2240 {
2242 }
2243 
2244 ////////////////////////////////////////////////////////////////////////////////
2245 /// read array of Double_t from buffer
2246 
2248 {
2250 }
2251 
2252 ////////////////////////////////////////////////////////////////////////////////
2253 /// read array of Float16_t from buffer
2254 
2256  TStreamerElement * /*ele*/)
2257 {
2259 }
2260 
2261 ////////////////////////////////////////////////////////////////////////////////
2262 /// read array of Float16_t from buffer
2263 
2265  Double_t /* factor */,
2266  Double_t /* minvalue */)
2267 {
2269 }
2270 
2271 ////////////////////////////////////////////////////////////////////////////////
2272 /// read array of Float16_t from buffer
2273 
2275 {
2277 }
2278 
2279 ////////////////////////////////////////////////////////////////////////////////
2280 /// read array of Double32_t from buffer
2281 
2283  TStreamerElement * /*ele*/)
2284 {
2286 }
2287 
2288 ////////////////////////////////////////////////////////////////////////////////
2289 /// read array of Double32_t from buffer
2290 
2292  Double_t /* factor */,
2293  Double_t /* minvalue */)
2294 {
2296 }
2297 
2298 ////////////////////////////////////////////////////////////////////////////////
2299 /// read array of Double32_t from buffer
2300 
2302 {
2304 }
2305 
2306 ////////////////////////////////////////////////////////////////////////////////
2307 /// redefined here to avoid warning message from gcc
2308 
2309 void TBufferJSON::ReadFastArray(void * /*start*/, const TClass * /*cl*/,
2310  Int_t /*n*/, TMemberStreamer * /*s*/,
2311  const TClass * /*onFileClass*/)
2312 {
2313 }
2314 
2315 ////////////////////////////////////////////////////////////////////////////////
2316 /// redefined here to avoid warning message from gcc
2317 
2318 void TBufferJSON::ReadFastArray(void ** /*startp*/, const TClass * /*cl*/,
2319  Int_t /*n*/, Bool_t /*isPreAlloc*/,
2320  TMemberStreamer * /*s*/,
2321  const TClass * /*onFileClass*/)
2322 {
2323 }
2324 
2325 #define TJSONWriteArrayCompress(vname, arrsize, typname) \
2326  { \
2327  if ((fCompact < 10) || (arrsize < 6)) { \
2328  fValue.Append("["); \
2329  for (Int_t indx=0;indx<arrsize;indx++) { \
2330  if (indx>0) fValue.Append(fArraySepar.Data()); \
2331  JsonWriteBasic(vname[indx]); \
2332  } \
2333  fValue.Append("]"); \
2334  } else { \
2335  fValue.Append("{"); \
2336  fValue.Append(TString::Format("\"$arr\":\"%s\"%s\"len\":%d",typname,fArraySepar.Data(),arrsize)); \
2337  Int_t aindx(0), bindx(arrsize); \
2338  while ((aindx<arrsize) && (vname[aindx]==0)) aindx++; \
2339  while ((aindx<bindx) && (vname[bindx-1]==0)) bindx--; \
2340  if (aindx<bindx) { \
2341  TString suffix(""); \
2342  Int_t p(aindx), suffixcnt(-1), lastp(0); \
2343  while (p<bindx) { \
2344  if (vname[p]==0) { p++; continue; } \
2345  Int_t p0(p++), pp(0), nsame(1); \
2346  if (fCompact < 20) { pp = bindx; p = bindx+1; nsame = 0; } \
2347  for(;p<=bindx;++p) { \
2348  if ((p<bindx) && (vname[p]==vname[p-1])) { nsame++; continue; } \
2349  if (vname[p-1]==0) { \
2350  if (nsame>9) { nsame = 0; break; } \
2351  } else \
2352  if (nsame>5) { \
2353  if (pp) { p = pp; nsame = 0; } else pp = p; \
2354  break; \
2355  } \
2356  pp = p; nsame = 1; \
2357  } \
2358  if (pp<=p0) continue; \
2359  if (++suffixcnt > 0) suffix.Form("%d",suffixcnt); \
2360  if (p0!=lastp) fValue.Append(TString::Format("%s\"p%s\":%d", fArraySepar.Data(), suffix.Data(), p0)); \
2361  lastp = pp; /* remember cursor, it may be the same */ \
2362  fValue.Append(TString::Format("%s\"v%s\":", fArraySepar.Data(), suffix.Data())); \
2363  if ((nsame > 1) || (pp-p0 == 1)) { \
2364  JsonWriteBasic(vname[p0]); \
2365  if (nsame>1) fValue.Append(TString::Format("%s\"n%s\":%d", fArraySepar.Data(), suffix.Data(), nsame)); \
2366  } else { \
2367  fValue.Append("["); \
2368  for (Int_t indx=p0;indx<pp;indx++) { \
2369  if (indx>p0) fValue.Append(fArraySepar.Data()); \
2370  JsonWriteBasic(vname[indx]); \
2371  } \
2372  fValue.Append("]"); \
2373  } \
2374  } \
2375  } \
2376  fValue.Append("}"); \
2377  } \
2378  }
2379 
2380 // macro call TBufferJSON method without typname
2381 #define TJSONWriteConstChar(vname,arrsize,typname) \
2382  { \
2383  JsonWriteConstChar(vname, arrsize); \
2384  } \
2385 
2386 
2387 // macro to write array, which include size
2388 #define TBufferJSON_WriteArray(vname, typname) \
2389  { \
2390  TJSONPushValue(); \
2391  TJSONWriteArrayCompress(vname, n, typname); \
2392  }
2393 
2394 
2395 ////////////////////////////////////////////////////////////////////////////////
2396 /// Write array of Bool_t to buffer
2397 
2399 {
2400  TBufferJSON_WriteArray(b,"Bool");
2401 }
2402 
2403 ////////////////////////////////////////////////////////////////////////////////
2404 /// Write array of Char_t to buffer
2405 
2407 {
2408  TBufferJSON_WriteArray(c,"Int8");
2409 }
2410 
2411 ////////////////////////////////////////////////////////////////////////////////
2412 /// Write array of UChar_t to buffer
2413 
2415 {
2416  TBufferJSON_WriteArray(c,"Uint8");
2417 }
2418 
2419 ////////////////////////////////////////////////////////////////////////////////
2420 /// Write array of Short_t to buffer
2421 
2423 {
2424  TBufferJSON_WriteArray(h,"Int16");
2425 }
2426 
2427 ////////////////////////////////////////////////////////////////////////////////
2428 /// Write array of UShort_t to buffer
2429 
2431 {
2432  TBufferJSON_WriteArray(h,"Uint16");
2433 }
2434 
2435 ////////////////////////////////////////////////////////////////////////////////
2436 /// Write array of Int_ to buffer
2437 
2439 {
2440  TBufferJSON_WriteArray(i,"Int32");
2441 }
2442 
2443 ////////////////////////////////////////////////////////////////////////////////
2444 /// Write array of UInt_t to buffer
2445 
2447 {
2448  TBufferJSON_WriteArray(i,"Uint32");
2449 }
2450 
2451 ////////////////////////////////////////////////////////////////////////////////
2452 /// Write array of Long_t to buffer
2453 
2455 {
2456  TBufferJSON_WriteArray(l,"Int64");
2457 }
2458 
2459 ////////////////////////////////////////////////////////////////////////////////
2460 /// Write array of ULong_t to buffer
2461 
2463 {
2464  TBufferJSON_WriteArray(l,"Uint64");
2465 }
2466 
2467 ////////////////////////////////////////////////////////////////////////////////
2468 /// Write array of Long64_t to buffer
2469 
2471 {
2472  TBufferJSON_WriteArray(l,"Int64");
2473 }
2474 
2475 ////////////////////////////////////////////////////////////////////////////////
2476 /// Write array of ULong64_t to buffer
2477 
2479 {
2480  TBufferJSON_WriteArray(l,"Uint64");
2481 }
2482 
2483 ////////////////////////////////////////////////////////////////////////////////
2484 /// Write array of Float_t to buffer
2485 
2487 {
2488  TBufferJSON_WriteArray(f,"Float32");
2489 }
2490 
2491 ////////////////////////////////////////////////////////////////////////////////
2492 /// Write array of Double_t to buffer
2493 
2495 {
2496  TBufferJSON_WriteArray(d,"Float64");
2497 }
2498 
2499 ////////////////////////////////////////////////////////////////////////////////
2500 /// Write array of Float16_t to buffer
2501 
2503  TStreamerElement * /*ele*/)
2504 {
2505  TBufferJSON_WriteArray(f,"Float32");
2506 }
2507 
2508 ////////////////////////////////////////////////////////////////////////////////
2509 /// Write array of Double32_t to buffer
2510 
2512  TStreamerElement * /*ele*/)
2513 {
2514  TBufferJSON_WriteArray(d,"Float64");
2515 }
2516 
2517 
2518 // write array without size attribute
2519 // macro also treat situation, when instead of one single array
2520 // chain of several elements should be produced
2521 #define TBufferJSON_WriteFastArray(vname,method,typname) \
2522  { \
2523  TJSONPushValue(); \
2524  if (n <= 0) { /*fJsonrCnt++;*/ fValue.Append("[]"); return; } \
2525  TStreamerElement* elem = Stack(0)->fElem; \
2526  if ((elem!=0) && (elem->GetArrayDim()>1) && (elem->GetArrayLength()==n)) { \
2527  TArrayI indexes(elem->GetArrayDim() - 1); \
2528  indexes.Reset(0); \
2529  Int_t cnt = 0, shift = 0, len = elem->GetMaxIndex(indexes.GetSize()); \
2530  while (cnt >= 0) { \
2531  if (indexes[cnt] >= elem->GetMaxIndex(cnt)) { \
2532  fValue.Append("]"); \
2533  indexes[cnt--] = 0; \
2534  if (cnt >= 0) indexes[cnt]++; \
2535  continue; \
2536  } \
2537  fValue.Append(indexes[cnt] == 0 ? "[" : fArraySepar.Data()); \
2538  if (++cnt == indexes.GetSize()) { \
2539  method((vname+shift), len, typname); \
2540  indexes[--cnt]++; \
2541  shift+=len; \
2542  } \
2543  } \
2544  } else { \
2545  method(vname, n, typname); \
2546  } \
2547  }
2548 
2549 ////////////////////////////////////////////////////////////////////////////////
2550 /// Write array of Bool_t to buffer
2551 
2553 {
2555 }
2556 
2557 ////////////////////////////////////////////////////////////////////////////////
2558 /// Write array of Char_t to buffer
2559 
2561 {
2563 }
2564 
2565 ////////////////////////////////////////////////////////////////////////////////
2566 /// Write array of Char_t to buffer
2567 
2569 {
2571 }
2572 
2573 
2574 ////////////////////////////////////////////////////////////////////////////////
2575 /// Write array of UChar_t to buffer
2576 
2578 {
2580 }
2581 
2582 ////////////////////////////////////////////////////////////////////////////////
2583 /// Write array of Short_t to buffer
2584 
2586 {
2588 }
2589 
2590 ////////////////////////////////////////////////////////////////////////////////
2591 /// Write array of UShort_t to buffer
2592 
2594 {
2596 }
2597 
2598 ////////////////////////////////////////////////////////////////////////////////
2599 /// Write array of Int_t to buffer
2600 
2602 {
2604 }
2605 
2606 ////////////////////////////////////////////////////////////////////////////////
2607 /// Write array of UInt_t to buffer
2608 
2610 {
2612 }
2613 
2614 ////////////////////////////////////////////////////////////////////////////////
2615 /// Write array of Long_t to buffer
2616 
2618 {
2620 }
2621 
2622 ////////////////////////////////////////////////////////////////////////////////
2623 /// Write array of ULong_t to buffer
2624 
2626 {
2628 }
2629 
2630 ////////////////////////////////////////////////////////////////////////////////
2631 /// Write array of Long64_t to buffer
2632 
2634 {
2636 }
2637 
2638 ////////////////////////////////////////////////////////////////////////////////
2639 /// Write array of ULong64_t to buffer
2640 
2642 {
2644 }
2645 
2646 ////////////////////////////////////////////////////////////////////////////////
2647 /// Write array of Float_t to buffer
2648 
2650 {
2652 }
2653 
2654 ////////////////////////////////////////////////////////////////////////////////
2655 /// Write array of Double_t to buffer
2656 
2658 {
2660 }
2661 
2662 ////////////////////////////////////////////////////////////////////////////////
2663 /// Write array of Float16_t to buffer
2664 
2666  TStreamerElement * /*ele*/)
2667 {
2669 }
2670 
2671 ////////////////////////////////////////////////////////////////////////////////
2672 /// Write array of Double32_t to buffer
2673 
2675  TStreamerElement * /*ele*/)
2676 {
2678 }
2679 
2680 ////////////////////////////////////////////////////////////////////////////////
2681 /// Recall TBuffer function to avoid gcc warning message
2682 
2683 void TBufferJSON::WriteFastArray(void *start, const TClass *cl, Int_t n,
2684  TMemberStreamer *streamer)
2685 {
2686  if (gDebug > 2)
2687  Info("WriteFastArray", "void *start cl %s n %d streamer %p",
2688  cl ? cl->GetName() : "---", n, streamer);
2689 
2690  if (streamer) {
2692  (*streamer)(*this, start, 0);
2693  return;
2694  }
2695 
2696  if (n<0) {
2697  // special handling of empty StreamLoop
2698  AppendOutput("null");
2700  } else {
2701 
2702  char *obj = (char *)start;
2703  if (!n) n = 1;
2704  int size = cl->Size();
2705 
2706  TArrayIndexProducer indexes(Stack(0)->fElem, n, fArraySepar.Data());
2707 
2708  if (indexes.IsArray()) {
2710  AppendOutput(indexes.GetBegin());
2711  }
2712 
2713  for (Int_t j = 0; j < n; j++, obj += size) {
2714 
2715  if (j>0) AppendOutput(indexes.NextSeparator());
2716 
2717  JsonWriteObject(obj, cl, kFALSE);
2718 
2719  if (indexes.IsArray() && (fValue.Length() > 0)) {
2721  fValue.Clear();
2722  }
2723  }
2724 
2725  if (indexes.IsArray())
2726  AppendOutput(indexes.GetEnd());
2727  }
2728 
2729  if (Stack(0)->fIndx)
2730  AppendOutput(Stack(0)->fIndx->NextSeparator());
2731 }
2732 
2733 ////////////////////////////////////////////////////////////////////////////////
2734 /// Recall TBuffer function to avoid gcc warning message
2735 
2737  Bool_t isPreAlloc, TMemberStreamer *streamer)
2738 {
2739  if (gDebug > 2)
2740  Info("WriteFastArray", "void **startp cl %s n %d streamer %p",
2741  cl->GetName(), n, streamer);
2742 
2743  if (streamer) {
2745  (*streamer)(*this, (void *)start, 0);
2746  return 0;
2747  }
2748 
2749  if (n<=0) return 0;
2750 
2751  Int_t res = 0;
2752 
2753  TArrayIndexProducer indexes(Stack(0)->fElem, n, fArraySepar.Data());
2754 
2755  if (indexes.IsArray()) {
2757  AppendOutput(indexes.GetBegin());
2758  }
2759 
2760  for (Int_t j = 0; j < n; j++) {
2761 
2762  if (j>0) AppendOutput(indexes.NextSeparator());
2763 
2764  if (!isPreAlloc) {
2765  res |= WriteObjectAny(start[j], cl);
2766  } else {
2767  if (!start[j]) start[j] = ((TClass *)cl)->New();
2768  // ((TClass*)cl)->Streamer(start[j],*this);
2769  JsonWriteObject(start[j], cl, kFALSE);
2770  }
2771 
2772  if (indexes.IsArray() && (fValue.Length() > 0)) {
2774  fValue.Clear();
2775  }
2776  }
2777 
2778  if (indexes.IsArray())
2779  AppendOutput(indexes.GetEnd());
2780 
2781  if (Stack(0)->fIndx)
2782  AppendOutput(Stack(0)->fIndx->NextSeparator());
2783 
2784  return res;
2785 }
2786 
2787 ////////////////////////////////////////////////////////////////////////////////
2788 /// stream object to/from buffer
2789 
2790 void TBufferJSON::StreamObject(void *obj, const std::type_info &typeinfo,
2791  const TClass * /* onFileClass */)
2792 {
2793  StreamObject(obj, TClass::GetClass(typeinfo));
2794 }
2795 
2796 ////////////////////////////////////////////////////////////////////////////////
2797 /// stream object to/from buffer
2798 
2799 void TBufferJSON::StreamObject(void *obj, const char *className,
2800  const TClass * /* onFileClass */)
2801 {
2802  StreamObject(obj, TClass::GetClass(className));
2803 }
2804 
2806 {
2807  // stream object to/from buffer
2808 
2809  StreamObject(obj, obj ? obj->IsA() : TObject::Class());
2810 }
2811 
2812 ////////////////////////////////////////////////////////////////////////////////
2813 /// stream object to/from buffer
2814 
2815 void TBufferJSON::StreamObject(void *obj, const TClass *cl,
2816  const TClass * /* onfileClass */)
2817 {
2818  if (gDebug > 3)
2819  Info("StreamObject", "Class: %s", (cl ? cl->GetName() : "none"));
2820 
2821  JsonWriteObject(obj, cl);
2822 }
2823 
2824 ////////////////////////////////////////////////////////////////////////////////
2825 /// Reads Bool_t value from buffer
2826 
2828 {
2829 }
2830 
2831 ////////////////////////////////////////////////////////////////////////////////
2832 /// Reads Char_t value from buffer
2833 
2835 {
2836 }
2837 
2838 ////////////////////////////////////////////////////////////////////////////////
2839 /// Reads UChar_t value from buffer
2840 
2842 {
2843 }
2844 
2845 ////////////////////////////////////////////////////////////////////////////////
2846 /// Reads Short_t value from buffer
2847 
2849 {
2850 }
2851 
2852 ////////////////////////////////////////////////////////////////////////////////
2853 /// Reads UShort_t value from buffer
2854 
2856 {
2857 }
2858 
2859 ////////////////////////////////////////////////////////////////////////////////
2860 /// Reads Int_t value from buffer
2861 
2863 {
2864 }
2865 
2866 ////////////////////////////////////////////////////////////////////////////////
2867 /// Reads UInt_t value from buffer
2868 
2870 {
2871 }
2872 
2873 ////////////////////////////////////////////////////////////////////////////////
2874 /// Reads Long_t value from buffer
2875 
2877 {
2878 }
2879 
2880 ////////////////////////////////////////////////////////////////////////////////
2881 /// Reads ULong_t value from buffer
2882 
2884 {
2885 }
2886 
2887 ////////////////////////////////////////////////////////////////////////////////
2888 /// Reads Long64_t value from buffer
2889 
2891 {
2892 }
2893 
2894 ////////////////////////////////////////////////////////////////////////////////
2895 /// Reads ULong64_t value from buffer
2896 
2898 {
2899 }
2900 
2901 ////////////////////////////////////////////////////////////////////////////////
2902 /// Reads Float_t value from buffer
2903 
2905 {
2906 }
2907 
2908 ////////////////////////////////////////////////////////////////////////////////
2909 /// Reads Double_t value from buffer
2910 
2912 {
2913 }
2914 
2915 ////////////////////////////////////////////////////////////////////////////////
2916 /// Reads array of characters from buffer
2917 
2919 {
2920 }
2921 
2922 ////////////////////////////////////////////////////////////////////////////////
2923 /// Reads a TString
2924 
2926 {
2927 }
2928 
2929 ////////////////////////////////////////////////////////////////////////////////
2930 /// Reads a std::string
2931 
2932 void TBufferJSON::ReadStdString(std::string * /*s*/)
2933 {
2934 }
2935 
2936 ////////////////////////////////////////////////////////////////////////////////
2937 /// Reads a char* string
2938 
2939 void TBufferJSON::ReadCharStar(char* &/*s*/)
2940 {
2941 }
2942 
2943 ////////////////////////////////////////////////////////////////////////////////
2944 /// Writes Bool_t value to buffer
2945 
2947 {
2948  TJSONPushValue();
2949 
2950  JsonWriteBasic(b);
2951 }
2952 
2953 ////////////////////////////////////////////////////////////////////////////////
2954 /// Writes Char_t value to buffer
2955 
2957 {
2958  TJSONPushValue();
2959 
2960  JsonWriteBasic(c);
2961 }
2962 
2963 ////////////////////////////////////////////////////////////////////////////////
2964 /// Writes UChar_t value to buffer
2965 
2967 {
2968  TJSONPushValue();
2969 
2970  JsonWriteBasic(c);
2971 }
2972 
2973 ////////////////////////////////////////////////////////////////////////////////
2974 /// Writes Short_t value to buffer
2975 
2977 {
2978  TJSONPushValue();
2979 
2980  JsonWriteBasic(h);
2981 }
2982 
2983 ////////////////////////////////////////////////////////////////////////////////
2984 /// Writes UShort_t value to buffer
2985 
2987 {
2988  TJSONPushValue();
2989 
2990  JsonWriteBasic(h);
2991 }
2992 
2993 ////////////////////////////////////////////////////////////////////////////////
2994 /// Writes Int_t value to buffer
2995 
2997 {
2998  TJSONPushValue();
2999 
3000  JsonWriteBasic(i);
3001 }
3002 
3003 ////////////////////////////////////////////////////////////////////////////////
3004 /// Writes UInt_t value to buffer
3005 
3007 {
3008  TJSONPushValue();
3009 
3010  JsonWriteBasic(i);
3011 }
3012 
3013 ////////////////////////////////////////////////////////////////////////////////
3014 /// Writes Long_t value to buffer
3015 
3017 {
3018  TJSONPushValue();
3019 
3020  JsonWriteBasic(l);
3021 }
3022 
3023 ////////////////////////////////////////////////////////////////////////////////
3024 /// Writes ULong_t value to buffer
3025 
3027 {
3028  TJSONPushValue();
3029 
3030  JsonWriteBasic(l);
3031 }
3032 
3033 ////////////////////////////////////////////////////////////////////////////////
3034 /// Writes Long64_t value to buffer
3035 
3037 {
3038  TJSONPushValue();
3039 
3040  JsonWriteBasic(l);
3041 }
3042 
3043 ////////////////////////////////////////////////////////////////////////////////
3044 /// Writes ULong64_t value to buffer
3045 
3047 {
3048  TJSONPushValue();
3049 
3050  JsonWriteBasic(l);
3051 }
3052 
3053 ////////////////////////////////////////////////////////////////////////////////
3054 /// Writes Float_t value to buffer
3055 
3057 {
3058  TJSONPushValue();
3059 
3060  JsonWriteBasic(f);
3061 }
3062 
3063 ////////////////////////////////////////////////////////////////////////////////
3064 /// Writes Double_t value to buffer
3065 
3067 {
3068  TJSONPushValue();
3069 
3070  JsonWriteBasic(d);
3071 }
3072 
3073 ////////////////////////////////////////////////////////////////////////////////
3074 /// Writes array of characters to buffer
3075 
3077 {
3078  TJSONPushValue();
3079 
3080  JsonWriteConstChar(c);
3081 }
3082 
3083 ////////////////////////////////////////////////////////////////////////////////
3084 /// Writes a TString
3085 
3087 {
3088  TJSONPushValue();
3089 
3090  JsonWriteConstChar(s.Data(), s.Length());
3091 }
3092 
3093 ////////////////////////////////////////////////////////////////////////////////
3094 /// Writes a std::string
3095 
3096 void TBufferJSON::WriteStdString(const std::string *s)
3097 {
3098  TJSONPushValue();
3099 
3100  if (s) JsonWriteConstChar(s->c_str(), s->length());
3101  else JsonWriteConstChar("",0);
3102 
3103 }
3104 
3105 ////////////////////////////////////////////////////////////////////////////////
3106 /// Writes a char*
3107 
3109 {
3110  TJSONPushValue();
3111 
3112  JsonWriteConstChar(s);
3113 }
3114 
3115 ////////////////////////////////////////////////////////////////////////////////
3116 /// converts Char_t to string and add to json value buffer
3117 
3119 {
3120  char buf[50];
3121  snprintf(buf, sizeof(buf), "%d", value);
3122  fValue.Append(buf);
3123 }
3124 
3125 ////////////////////////////////////////////////////////////////////////////////
3126 /// converts Short_t to string and add to json value buffer
3127 
3129 {
3130  char buf[50];
3131  snprintf(buf, sizeof(buf), "%hd", value);
3132  fValue.Append(buf);
3133 }
3134 
3135 ////////////////////////////////////////////////////////////////////////////////
3136 /// converts Int_t to string and add to json value buffer
3137 
3139 {
3140  char buf[50];
3141  snprintf(buf, sizeof(buf), "%d", value);
3142  fValue.Append(buf);
3143 }
3144 
3145 ////////////////////////////////////////////////////////////////////////////////
3146 /// converts Long_t to string and add to json value buffer
3147 
3149 {
3150  char buf[50];
3151  snprintf(buf, sizeof(buf), "%ld", value);
3152  fValue.Append(buf);
3153 }
3154 
3155 ////////////////////////////////////////////////////////////////////////////////
3156 /// converts Long64_t to string and add to json value buffer
3157 
3159 {
3160  char buf[50];
3161  snprintf(buf, sizeof(buf), FLong64, value);
3162  fValue.Append(buf);
3163 }
3164 
3165 ////////////////////////////////////////////////////////////////////////////////
3166 /// method compress float string, excluding exp and/or move float point
3167 /// - 1.000000e-01 -> 0.1
3168 /// - 3.750000e+00 -> 3.75
3169 /// - 3.750000e-03 -> 0.00375
3170 /// - 3.750000e-04 -> 3.75e-4
3171 /// - 1.100000e-10 -> 1.1e-10
3172 
3173 void TBufferJSON::CompactFloatString(char* sbuf, unsigned len)
3174 {
3175  char* pnt = 0, *exp = 0, *lastdecimal = 0, *s = sbuf;
3176  bool negative_exp = false;
3177  int power = 0;
3178  while(*s && --len) {
3179  switch (*s) {
3180  case '.': pnt = s; break;
3181  case 'E':
3182  case 'e': exp = s; break;
3183  case '-': if (exp) negative_exp = true; break;
3184  case '+': break;
3185  default: // should be digits from '0' to '9'
3186  if ((*s <'0') || (*s >'9')) return;
3187  if (exp) power = power*10 + (*s - '0'); else
3188  if (pnt && *s!='0') lastdecimal = s;
3189  break;
3190  }
3191  ++s;
3192  }
3193  if (*s) return; // if end-of-string was not found
3194 
3195  if (!exp) {
3196  // value without exponent like 123.4569000
3197  if (pnt) {
3198  if (lastdecimal) *(lastdecimal+1) = 0;
3199  else *pnt = 0;
3200  }
3201  } else
3202  if (power==0) {
3203  if (lastdecimal) *(lastdecimal+1) = 0; else
3204  if (pnt) *pnt = 0;
3205  } else
3206  if (!negative_exp && pnt && exp && (exp-pnt > power)) {
3207  // this is case of value 1.23000e+02
3208  // we can move point and exclude exponent easily
3209  for (int cnt=0;cnt<power;++cnt) {
3210  char tmp = *pnt;
3211  *pnt = *(pnt+1);
3212  *(++pnt) = tmp;
3213  }
3214  if (lastdecimal && (pnt<lastdecimal)) *(lastdecimal+1) = 0;
3215  else *pnt = 0;
3216  } else
3217  if (negative_exp && pnt && exp && (power < (s-exp))) {
3218  // this is small negative exponent like 1.2300e-02
3219  if (!lastdecimal) lastdecimal = pnt;
3220  *(lastdecimal+1) = 0;
3221  // copy most significant digit on the point place
3222  *pnt = *(pnt-1);
3223 
3224  for (char* pos = lastdecimal+1; pos>=pnt; --pos)
3225  *(pos+power) = *pos;
3226  *(pnt-1) = '0';
3227  *pnt = '.';
3228  for (int cnt=1;cnt<power;++cnt)
3229  *(pnt+cnt) = '0';
3230  } else
3231  if (pnt && exp) {
3232  // keep exponent, but non-significant zeros
3233  if (lastdecimal) pnt = lastdecimal+1;
3234  // copy exponent sign
3235  *pnt++ = *exp++;
3236  if (*exp=='+') ++exp; else
3237  if (*exp=='-') *pnt++ = *exp++;
3238  // exclude zeros in the begin of exponent
3239  while (*exp=='0') ++exp;
3240  while (*exp) *pnt++ = *exp++;
3241  *pnt = 0;
3242  }
3243 }
3244 
3245 ////////////////////////////////////////////////////////////////////////////////
3246 /// converts Float_t to string and add to json value buffer
3247 
3249 {
3250  char buf[200];
3251  // this is just check if float value looks like integer and can be stored in more compact form
3252  // default should be storage with fgFloatFmt, which will be optimized afterwards anyway
3253  if ((value == std::nearbyint(value)) && (std::abs(value) < 1e15)) {
3254  snprintf(buf, sizeof(buf), "%1.0f", value);
3255  } else {
3256  snprintf(buf, sizeof(buf), fgFloatFmt, value);
3257  CompactFloatString(buf, sizeof(buf));
3258  }
3259  fValue.Append(buf);
3260 }
3261 
3262 ////////////////////////////////////////////////////////////////////////////////
3263 /// converts Double_t to string and add to json value buffer
3264 
3266 {
3267  char buf[200];
3268  // this is just check if float value looks like integer and can be stored in more compact form
3269  // default should be storage with fgDoubleFmt, which will be optimized afterwards anyway
3270  if ((value == std::nearbyint(value)) && (std::abs(value) < 1e25)) {
3271  snprintf(buf, sizeof(buf), "%1.0f", value);
3272  } else {
3273  snprintf(buf, sizeof(buf), fgDoubleFmt, value);
3274  CompactFloatString(buf, sizeof(buf));
3275  }
3276  fValue.Append(buf);
3277 }
3278 
3279 ////////////////////////////////////////////////////////////////////////////////
3280 /// converts Bool_t to string and add to json value buffer
3281 
3283 {
3284  fValue.Append(value ? "true" : "false");
3285 }
3286 
3287 ////////////////////////////////////////////////////////////////////////////////
3288 /// converts UChar_t to string and add to json value buffer
3289 
3291 {
3292  char buf[50];
3293  snprintf(buf, sizeof(buf), "%u", value);
3294  fValue.Append(buf);
3295 }
3296 
3297 ////////////////////////////////////////////////////////////////////////////////
3298 /// converts UShort_t to string and add to json value buffer
3299 
3301 {
3302  char buf[50];
3303  snprintf(buf, sizeof(buf), "%hu", value);
3304  fValue.Append(buf);
3305 }
3306 
3307 ////////////////////////////////////////////////////////////////////////////////
3308 /// converts UInt_t to string and add to json value buffer
3309 
3311 {
3312  char buf[50];
3313  snprintf(buf, sizeof(buf), "%u", value);
3314  fValue.Append(buf);
3315 }
3316 
3317 ////////////////////////////////////////////////////////////////////////////////
3318 /// converts ULong_t to string and add to json value buffer
3319 
3321 {
3322  char buf[50];
3323  snprintf(buf, sizeof(buf), "%lu", value);
3324  fValue.Append(buf);
3325 }
3326 
3327 ////////////////////////////////////////////////////////////////////////////////
3328 /// converts ULong64_t to string and add to json value buffer
3329 
3331 {
3332  char buf[50];
3333  snprintf(buf, sizeof(buf), FULong64, value);
3334  fValue.Append(buf);
3335 }
3336 
3337 ////////////////////////////////////////////////////////////////////////////////
3338 /// writes string value, processing all kind of special characters
3339 
3340 void TBufferJSON::JsonWriteConstChar(const char* value, Int_t len)
3341 {
3342  if (value==0) {
3343 
3344  fValue.Append("\"\"");
3345 
3346  } else {
3347 
3348  fValue.Append("\"");
3349 
3350  if (len<0) len = strlen(value);
3351 
3352  for (Int_t n=0;n<len;n++) {
3353  char c = value[n];
3354  if (c==0) break;
3355  switch(c) {
3356  case '\n':
3357  fValue.Append("\\n");
3358  break;
3359  case '\t':
3360  fValue.Append("\\t");
3361  break;
3362  case '\"':
3363  fValue.Append("\\\"");
3364  break;
3365  case '\\':
3366  fValue.Append("\\\\");
3367  break;
3368  case '\b':
3369  fValue.Append("\\b");
3370  break;
3371  case '\f':
3372  fValue.Append("\\f");
3373  break;
3374  case '\r':
3375  fValue.Append("\\r");
3376  break;
3377  case '/':
3378  fValue.Append("\\/");
3379  break;
3380  default:
3381  if ((c > 31) && (c < 127))
3382  fValue.Append(c);
3383  else
3384  fValue.Append(TString::Format("\\u%04x", (unsigned) c));
3385  }
3386  }
3387 
3388  fValue.Append("\"");
3389  }
3390 }
3391 
3392 
3393 ////////////////////////////////////////////////////////////////////////////////
3394 /// set printf format for float/double members, default "%e"
3395 /// to change format only for doubles, use SetDoubleFormat
3396 
3397 void TBufferJSON::SetFloatFormat(const char *fmt)
3398 {
3399  if (fmt == 0) fmt = "%e";
3400  fgFloatFmt = fmt;
3401  fgDoubleFmt = fmt;
3402 }
3403 
3404 ////////////////////////////////////////////////////////////////////////////////
3405 /// return current printf format for float members, default "%e"
3406 
3408 {
3409  return fgFloatFmt;
3410 }
3411 
3412 ////////////////////////////////////////////////////////////////////////////////
3413 /// set printf format for double members, default "%.14e"
3414 /// use it after SetFloatFormat, which also overwrites format for doubles
3415 
3416 void TBufferJSON::SetDoubleFormat(const char *fmt)
3417 {
3418  if (fmt == 0) fmt = "%.14e";
3419  fgDoubleFmt = fmt;
3420 }
3421 
3422 ////////////////////////////////////////////////////////////////////////////////
3423 /// return current printf format for double members, default "%.14e"
3424 
3426 {
3427  return fgDoubleFmt;
3428 }
3429 
3430 ////////////////////////////////////////////////////////////////////////////////
3431 /// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
3432 /// The collection needs to be a split TClonesArray or a split vector of pointers.
3433 
3435  void *obj)
3436 {
3437  TVirtualStreamerInfo *info = sequence.fStreamerInfo;
3438  IncrementLevel(info);
3439 
3440  if (gDebug) {
3441  //loop on all active members
3442  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3443  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3444  iter != end; ++iter) {
3445  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
3446  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
3447  (*iter).PrintDebug(*this, obj);
3448  (*iter)(*this, obj);
3449  }
3450  } else {
3451  //loop on all active members
3452  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3453  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3454  iter != end; ++iter) {
3455  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
3456  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
3457  (*iter)(*this, obj);
3458  }
3459  }
3460  DecrementLevel(info);
3461  return 0;
3462 }
3463 
3464 ////////////////////////////////////////////////////////////////////////////////
3465 /// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
3466 /// The collection needs to be a split TClonesArray or a split vector of pointers.
3467 
3469  void *start_collection, void *end_collection)
3470 {
3471  TVirtualStreamerInfo *info = sequence.fStreamerInfo;
3472  IncrementLevel(info);
3473 
3474  if (gDebug) {
3475  //loop on all active members
3476  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3477  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3478  iter != end; ++iter) {
3479  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
3480  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
3481  (*iter).PrintDebug(*this, *(char **)start_collection); // Warning: This limits us to TClonesArray and vector of pointers.
3482  (*iter)(*this, start_collection, end_collection);
3483  }
3484  } else {
3485  //loop on all active members
3486  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3487  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3488  iter != end; ++iter) {
3489  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
3490  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
3491  (*iter)(*this, start_collection, end_collection);
3492  }
3493  }
3494  DecrementLevel(info);
3495  return 0;
3496 }
3497 
3498 ////////////////////////////////////////////////////////////////////////////////
3499 /// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
3500 
3502  void *start_collection, void *end_collection)
3503 {
3504  TVirtualStreamerInfo *info = sequence.fStreamerInfo;
3505  IncrementLevel(info);
3506 
3508  if (gDebug) {
3509 
3510  // Get the address of the first item for the PrintDebug.
3511  // (Performance is not essential here since we are going to print to
3512  // the screen anyway).
3513  void *arr0 = loopconfig->GetFirstAddress(start_collection, end_collection);
3514  // loop on all active members
3515  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3516  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3517  iter != end; ++iter) {
3518  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
3519  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
3520  (*iter).PrintDebug(*this, arr0);
3521  (*iter)(*this, start_collection, end_collection, loopconfig);
3522  }
3523  } else {
3524  //loop on all active members
3525  TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3526  for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3527  iter != end; ++iter) {
3528  // Idea: Try to remove this function call as it is really needed only for JSON streaming.
3529  SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem, (*iter).fConfiguration->fCompInfo->fType);
3530  (*iter)(*this, start_collection, end_collection, loopconfig);
3531  }
3532  }
3533  DecrementLevel(info);
3534  return 0;
3535 }
3536 
3537 
3538 ////////////////////////////////////////////////////////////////////////////////
3539 /// Interface to TStreamerInfo::WriteBufferClones.
3540 
3542 {
3543  Info("WriteClones", "Not yet tested");
3544 
3545  if (a != 0)
3546  JsonStreamCollection(a, a->IsA());
3547 
3548  return 0;
3549 }
3550 
3551 namespace {
3552  struct DynamicType {
3553  // Helper class to enable typeid on any address
3554  // Used in code similar to:
3555  // typeid( * (DynamicType*) void_ptr );
3556  virtual ~DynamicType() {}
3557  };
3558 }
3559 
3560 ////////////////////////////////////////////////////////////////////////////////
3561 /// Write object to I/O buffer.
3562 /// This function assumes that the value in 'obj' is the value stored in
3563 /// a pointer to a "ptrClass". The actual type of the object pointed to
3564 /// can be any class derived from "ptrClass".
3565 /// Return:
3566 /// - 0: failure
3567 /// - 1: success
3568 /// - 2: truncated success (i.e actual class is missing. Only ptrClass saved.)
3569 ///
3570 /// If 'cacheReuse' is true (default) upon seeing an object address a second time,
3571 /// we record the offset where its was written the first time rather than streaming
3572 /// the object a second time.
3573 /// If 'cacheReuse' is false, we always stream the object. This allows the (re)use
3574 /// of temporary object to store different data in the same buffer.
3575 
3576 Int_t TBufferJSON::WriteObjectAny(const void *obj, const TClass *ptrClass, Bool_t cacheReuse /* = kTRUE */)
3577 {
3578  if (!obj) {
3579  WriteObjectClass(0, 0, kTRUE);
3580  return 1;
3581  }
3582 
3583  if (!ptrClass) {
3584  Error("WriteObjectAny", "ptrClass argument may not be 0");
3585  return 0;
3586  }
3587 
3588  TClass *clActual = ptrClass->GetActualClass(obj);
3589 
3590  if (clActual == 0) {
3591  // The ptrClass is a class with a virtual table and we have no
3592  // TClass with the actual type_info in memory.
3593 
3594  DynamicType *d_ptr = (DynamicType *)obj;
3595  Warning("WriteObjectAny",
3596  "An object of type %s (from type_info) passed through a %s pointer was truncated (due a missing dictionary)!!!",
3597  typeid(*d_ptr).name(), ptrClass->GetName());
3598  WriteObjectClass(obj, ptrClass, cacheReuse);
3599  return 2;
3600  } else if (clActual && (clActual != ptrClass)) {
3601  const char *temp = (const char *) obj;
3602  temp -= clActual->GetBaseClassOffset(ptrClass);
3603  WriteObjectClass(temp, clActual, cacheReuse);
3604  return 1;
3605  } else {
3606  WriteObjectClass(obj, ptrClass, cacheReuse);
3607  return 1;
3608  }
3609 }
3610 
3611 ////////////////////////////////////////////////////////////////////////////////
3612 /// Function called by the Streamer functions to serialize object at p
3613 /// to buffer b. The optional argument info may be specified to give an
3614 /// alternative StreamerInfo instead of using the default StreamerInfo
3615 /// automatically built from the class definition.
3616 /// For more information, see class TStreamerInfo.
3617 
3618 Int_t TBufferJSON::WriteClassBuffer(const TClass *cl, void *pointer)
3619 {
3620 
3621  //build the StreamerInfo if first time for the class
3622  TStreamerInfo *sinfo = (TStreamerInfo *)const_cast<TClass *>(cl)->GetCurrentStreamerInfo();
3623  if (sinfo == 0) {
3624  //Have to be sure between the check and the taking of the lock if the current streamer has changed
3626  sinfo = (TStreamerInfo *)const_cast<TClass *>(cl)->GetCurrentStreamerInfo();
3627  if (sinfo == 0) {
3628  const_cast<TClass *>(cl)->BuildRealData(pointer);
3629  sinfo = new TStreamerInfo(const_cast<TClass *>(cl));
3630  const_cast<TClass *>(cl)->SetCurrentStreamerInfo(sinfo);
3631  const_cast<TClass *>(cl)->RegisterStreamerInfo(sinfo);
3632  if (gDebug > 0)
3633  printf("Creating StreamerInfo for class: %s, version: %d\n",
3634  cl->GetName(), cl->GetClassVersion());
3635  sinfo->Build();
3636  }
3637  } else if (!sinfo->IsCompiled()) {
3639  // Redo the test in case we have been victim of a data race on fIsCompiled.
3640  if (!sinfo->IsCompiled()) {
3641  const_cast<TClass *>(cl)->BuildRealData(pointer);
3642  sinfo->BuildOld();
3643  }
3644  }
3645 
3646  //write the class version number and reserve space for the byte count
3647  // UInt_t R__c = WriteVersion(cl, kTRUE);
3648 
3649  //NOTE: In the future Philippe wants this to happen via a custom action
3650  TagStreamerInfo(sinfo);
3651  ApplySequence(*(sinfo->GetWriteTextActions()), (char *)pointer);
3652 
3653  //write the byte count at the start of the buffer
3654  // SetByteCount(R__c, kTRUE);
3655 
3656  if (gDebug > 2)
3657  Info("WriteClassBuffer", "class: %s version %d done", cl->GetName(), cl->GetClassVersion());
3658  return 0;
3659 }
Abstract array base class.
Definition: TArray.h:31
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)
Ignored in TBufferJSON.
Ssiz_t Capacity() const
Definition: TString.h:333
#define TJSONPushValue()
An array of TObjects.
Definition: TObjArray.h:37
TString JsonWriteMember(const void *ptr, TDataMember *member, TClass *memberClass, Int_t arraylen)
Convert single data member to JSON structures Returns string with converted member.
virtual void WriteUChar(UChar_t c)
Writes UChar_t value to buffer.
virtual void WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele=0)
Write array of Float16_t to buffer.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
virtual Int_t WriteClones(TClonesArray *a, Int_t nobjects)
Interface to TStreamerInfo::WriteBufferClones.
virtual TClass * ReadClass(const TClass *cl=0, UInt_t *objTag=0)
suppressed function of TBuffer
virtual Int_t ReadStaticArray(Bool_t *b)
Read array of Bool_t from buffer.
long long Long64_t
Definition: RtypesCore.h:69
virtual Int_t ReadArray(Bool_t *&b)
Read array of Bool_t from buffer.
void JsonDisablePostprocessing()
virtual void ReadShort(Short_t &s)
Reads Short_t value from buffer.
virtual Int_t ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele=0)
Read array of Float16_t from buffer.
short Version_t
Definition: RtypesCore.h:61
virtual void WriteLong64(Long64_t l)
Writes Long64_t value to buffer.
#define TBufferJSON_ReadArray(tname, vname)
virtual TClass * GetClass() const =0
TLoopConfiguration * fLoopConfig
If this is a bundle of memberwise streaming action, this configures the looping.
Collectable string class.
Definition: TObjString.h:28
float Float_t
Definition: RtypesCore.h:53
virtual void ReadFloat(Float_t &f)
Reads Float_t value from buffer.
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 Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
virtual Int_t WriteObjectAny(const void *obj, const TClass *ptrClass, Bool_t cacheReuse=kTRUE)
Write object to I/O buffer.
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
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...
TString fSemicolon
0 - no any compression, 1 - no spaces in the begin, 2 - no new lines, 3 - no spaces at all ...
Definition: TBufferJSON.h:464
virtual void SkipObjectAny()
Skip any kind of object from buffer.
Int_t GetUnitSize() const
Get the sizeof the underlying type of the data member (i.e.
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual void ReadCharP(Char_t *c)
Reads array of characters from buffer.
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TH1 * h
Definition: legend2.C:5
virtual void DecrementLevel(TVirtualStreamerInfo *)
Function is called from TStreamerInfo WriteBuffer and ReadBuffer functions and decrease level in json...
TString fArraySepar
depending from compression level, " : " or ":"
Definition: TBufferJSON.h:465
virtual void ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue)
read array of Float16_t from buffer
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual void ReadBool(Bool_t &b)
Reads Bool_t value from buffer.
Int_t fCompact
stack of streamer infos
Definition: TBufferJSON.h:463
virtual void WriteDouble(Double_t d)
Writes Double_t value to buffer.
virtual void ReadLong64(Long64_t &l)
Reads Long64_t value from buffer.
virtual void ReadStdString(std::string *s)
Reads a std::string.
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
void JsonWriteBasic(Char_t value)
converts Char_t to string and add to json value buffer
#define gROOT
Definition: TROOT.h:402
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:703
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
static void SetDoubleFormat(const char *fmt="%.14e")
set printf format for double members, default "%.14e" use it after SetFloatFormat, which also overwrites format for doubles
virtual void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=0)
read array of Float16_t from buffer
virtual void WriteULong64(ULong64_t l)
Writes ULong64_t value to buffer.
Basic string class.
Definition: TString.h:125
Int_t JsonSpecialClass(const TClass *cl) const
return non-zero value when class has special handling in JSON it is TCollection (-130), TArray (100), TString (110), std::string (120) and STL containers (1..6)
Int_t GetArrayLength() const
virtual void ReadFastArray(Bool_t *b, Int_t n)
read array of Bool_t from buffer
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
#define TJSONWriteConstChar(vname, arrsize, typname)
static const char * fgDoubleFmt
printf argument for floats, either "%f" or "%e" or "%10f" and so on
Definition: TBufferJSON.h:469
virtual void ReadLong(Long_t &l)
Reads Long_t value from buffer.
virtual void WriteLong(Long_t l)
Writes Long_t value to buffer.
virtual Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:249
Option_t * GetOption() const
Definition: TCollection.h:249
virtual void SetArrayDim(Int_t dim)
Set number of array dimensions.
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Int_t GetArrayDim() const
virtual void WriteFastArrayString(const Char_t *c, Int_t n)
Write array of Char_t to buffer.
#define malloc
Definition: civetweb.c:818
virtual void SetMaxIndex(Int_t dim, Int_t max)
set maximum index for array with dimension dim
Array of integers (32 bits per element).
Definition: TArrayI.h:27
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
#define TBufferJSON_WriteFastArray(vname, method, typname)
virtual void WriteInt(Int_t i)
Writes Int_t value to buffer.
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:628
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)
suppressed function of TBuffer
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition: TClass.cxx:2710
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:505
virtual void ReadChar(Char_t &c)
Reads Char_t value from buffer.
#define FULong64
Definition: TBufferJSON.cxx:74
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=0)
read array of Double32_t from buffer
virtual void * GetFirstAddress(void *start, const void *end) const =0
virtual void WriteFastArray(const Bool_t *b, Int_t n)
Write array of Bool_t to buffer.
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2365
virtual void WriteObject(const TObject *obj, Bool_t cacheReuse=kTRUE)
Convert object into json structures.
void Class()
Definition: Class.C:29
TString fOutBuffer
Definition: TBufferJSON.h:457
virtual void ReadUShort(UShort_t &s)
Reads UShort_t value from buffer.
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1150
virtual void ReadDouble(Double_t &d)
Reads Double_t value from buffer.
TJSONStackObj * Stack(Int_t depth=0)
return stack object of specified depth
TString & Append(const char *cs)
Definition: TString.h:495
std::map< const void *, unsigned > fJsonrMap
buffer for current value
Definition: TBufferJSON.h:460
Long_t GetThisOffset() const
Definition: TRealData.h:55
unsigned fJsonrCnt
map of recorded objects, used in JsonR to restore references
Definition: TBufferJSON.h:461
virtual void ReadCharStar(char *&s)
Reads a char* string.
TDataType * GetDataType() const
Definition: TDataMember.h:74
TObjArray fStack
counter for all objects and arrays
Definition: TBufferJSON.h:462
virtual void ReadUChar(UChar_t &c)
Reads UChar_t value from buffer.
#define TBufferJSON_ReadStaticArray(vname)
void Set(Int_t n)
Set size of this array to n ints.
Definition: TArrayI.cxx:105
Base class of the Configurations for the member wise looping routines.
void SetCompact(int level)
virtual void WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=0)
Write array of Double32_t to buffer.
void JsonWriteConstChar(const char *value, Int_t len=-1)
writes string value, processing all kind of special characters
Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
virtual Int_t ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele=0)
Read array of Double32_t from buffer.
TString fNumericLocale
depending from compression level, ", " or ","
Definition: TBufferJSON.h:466
virtual void ReadInt(Int_t &i)
Reads Int_t value from buffer.
Int_t GetType() const
Definition: TDataType.h:68
TString fValue
current output buffer for json code
Definition: TBufferJSON.h:459
virtual void SetStreamerElementNumber(TStreamerElement *elem, Int_t comp_type)
Function is called from TStreamerInfo WriteBuffer and Readbuffer functions and add/verify next elemen...
virtual void WriteStdString(const std::string *s)
Writes a std::string.
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
virtual void IncrementLevel(TVirtualStreamerInfo *)
Function is called from TStreamerInfo WriteBuffer and ReadBuffer functions and indent new level in js...
virtual void WriteObjectClass(const void *actualObjStart, const TClass *actualClass, Bool_t cacheReuse)
Write object to buffer. Only used from TBuffer.
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)
suppressed function of TBuffer
static Int_t ExportToFile(const char *filename, const TObject *obj, const char *option=0)
Convert object into JSON and store in text file Returns size of the produce file Used in TObject::Sav...
TClass * GetClass() const
void BuildOld()
rebuild the TStreamerInfo structure
virtual void TagStreamerInfo(TVirtualStreamerInfo *)
Definition: TBufferJSON.h:232
Int_t GetSize() const
Definition: TArray.h:47
virtual void ReadULong(ULong_t &l)
Reads ULong_t value from buffer.
SVector< double, 2 > v
Definition: Dict.h:5
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
auto * a
Definition: textangle.C:12
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2527
static const char * GetDoubleFormat()
return current printf format for double members, default "%.14e"
PyObject * fValue
virtual void ClassBegin(const TClass *, Version_t=-1)
Should be called in the beginning of custom class streamer.
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.
TString * fOutput
main output buffer for json code
Definition: TBufferJSON.h:458
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
TDataMember * GetDataMember() const
Definition: TRealData.h:53
Collection abstract base class.
Definition: TCollection.h:63
void AppendOutput(const char *line0, const char *line1=0)
Info("AppendOutput"," &#39;%s&#39; &#39;%s&#39;", line0, line1?line1 : "---");.
virtual void ReadDouble32(Double_t *d, TStreamerElement *ele=0)
read a Double32_t from the buffer
Int_t GetMaxIndex(Int_t i) const
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
virtual void SkipVersion(const TClass *cl=0)
Skip class version from I/O buffer.
Ssiz_t Length() const
Definition: TString.h:386
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5434
short Short_t
Definition: RtypesCore.h:35
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
Int_t GetArrayDim() const
Return number of array dimensions.
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2805
static const char * fgFloatFmt
stored value of setlocale(LC_NUMERIC), which should be recovered at the end
Definition: TBufferJSON.h:468
virtual void WriteUShort(UShort_t s)
Writes UShort_t value to buffer.
void WorkWithElement(TStreamerElement *elem, Int_t)
This is call-back from streamer which indicates that class member will be streamed Name of element us...
virtual void WriteBool(Bool_t b)
Writes Bool_t value to buffer.
virtual void WriteDouble32(Double_t *d, TStreamerElement *ele=0)
write a Double32_t to the buffer
void WorkWithClass(TStreamerInfo *info, const TClass *cl=0)
Prepares buffer to stream data of specified class.
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
void JsonStartElement(const TStreamerElement *elem, const TClass *base_class=0)
virtual void ReadTString(TString &s)
Reads a TString.
virtual void WriteFloat(Float_t f)
Writes Float_t value to buffer.
#define FLong64
Definition: TBufferJSON.cxx:73
const Bool_t kFALSE
Definition: RtypesCore.h:88
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
long Long_t
Definition: RtypesCore.h:50
virtual void WriteFastArrayFloat16(const Float_t *d, Int_t n, TStreamerElement *ele=0)
Write array of Float16_t to buffer.
Version_t GetClassVersion() const
Definition: TClass.h:391
virtual void WriteTString(const TString &s)
Writes a TString.
void Build()
Build the I/O data structure for the current class version.
static const char * GetFloatFormat()
return current printf format for float members, default "%e"
virtual void WriteShort(Short_t s)
Writes Short_t value to buffer.
Class for serializing object into JavaScript Object Notation (JSON) format.
Definition: TBufferJSON.h:30
#define ClassImp(name)
Definition: Rtypes.h:359
virtual void ReadFloat16(Float_t *f, TStreamerElement *ele=0)
read a Float16_t from the buffer
double Double_t
Definition: RtypesCore.h:55
virtual Bool_t CheckObject(const TObject *)
Check that object already stored in the buffer.
virtual void WriteUInt(UInt_t i)
Writes UInt_t value to buffer.
virtual void WriteFloat16(Float_t *f, TStreamerElement *ele=0)
write a Float16_t to the buffer
virtual void WriteULong(ULong_t l)
Writes ULong_t value to buffer.
virtual void WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=0)
Write array of Double32_t to buffer.
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:40
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:589
unsigned long long ULong64_t
Definition: RtypesCore.h:70
TList * GetListOfRealData() const
Definition: TClass.h:418
#define TJSONWriteArrayCompress(vname, arrsize, typname)
#define free
Definition: civetweb.c:821
unsigned long ULong_t
Definition: RtypesCore.h:51
static RooMathCoreReg dummy
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
static TString ConvertToJSON(const TObject *obj, Int_t compact=0, const char *member_name=0)
Converts object, inherited from TObject class, to JSON string Lower digit of compact parameter define...
virtual void * ReadObjectAny(const TClass *clCast)
Read object from buffer. Only used from TBuffer.
static constexpr double s
virtual void WriteCharStar(char *s)
Writes a char*.
#define R__LOCKGUARD(mutex)
TStreamerInfoActions::TActionSequence * GetWriteTextActions()
TBufferJSON()
Creates buffer object to serialize data into json.
void JsonWriteObject(const void *obj, const TClass *objClass, Bool_t check_map=kTRUE)
Write object to buffer If object was written before, only pointer will be stored If check_map==kFALSE...
virtual void ReadULong64(ULong64_t &l)
Reads ULong64_t value from buffer.
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:2887
virtual void ClassEnd(const TClass *)
Should be called at the end of custom streamer See TBufferJSON::ClassBegin for more details...
virtual Int_t ReadArrayDouble32(Double_t *&d, TStreamerElement *ele=0)
Read array of Double32_t from buffer.
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
static void SetFloatFormat(const char *fmt="%e")
set printf format for float/double members, default "%e" to change format only for doubles...
Int_t IsSTLContainer()
The return type is defined in TDictionary (kVector, kList, etc.)
TJSONStackObj * PopStack()
remove one level from stack
char Char_t
Definition: RtypesCore.h:29
virtual void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=0)
stream object to/from buffer
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5668
virtual void WriteChar(Char_t c)
Writes Char_t value to buffer.
An array of clone (identical) objects.
Definition: TClonesArray.h:32
const char * GetTypeName() const
virtual Int_t ReadArrayFloat16(Float_t *&f, TStreamerElement *ele=0)
Read array of Float16_t from buffer.
auto * l
Definition: textangle.C:4
virtual void WriteCharP(const Char_t *c)
Writes array of characters to buffer.
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
static void CompactFloatString(char *buf, unsigned len)
method compress float string, excluding exp and/or move float point
void PerformPostProcessing(TJSONStackObj *stack, const TClass *obj_cl=0)
Function is converts TObject and TString structures to more compact representation.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
TJSONStackObj * PushStack(Int_t inclevel=0)
add new level to the structures stack
#define TBufferJSON_ReadFastArray(vname)
#define snprintf
Definition: civetweb.c:822
Int_t fBufSize
Definition: TBuffer.h:47
void Reset()
Definition: TArrayI.h:47
#define TBufferJSON_WriteArray(vname, typname)
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition: TMap.cxx:235
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1975
void Add(TObject *obj)
Definition: TObjArray.h:73
void SetBaseVersion(Int_t v)
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)
Function called by the Streamer functions to serialize object at p to buffer b.
void JsonStreamCollection(TCollection *obj, const TClass *objClass)
store content of collection
unsigned char UChar_t
Definition: RtypesCore.h:34
Definition: first.py:1
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)
read version value from buffer
virtual ~TBufferJSON()
destroy buffer
virtual void WriteClass(const TClass *cl)
suppressed function of TBuffer
virtual void ReadFastArrayString(Char_t *c, Int_t n)
read array of Char_t from buffer
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:333
double exp(double)
Abstract Interface class describing Streamer information for one class.
Bool_t IsaPointer() const
Return true if data member is a pointer.
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t GetType() const
const Int_t n
Definition: legend1.C:16
virtual void WriteArray(const Bool_t *b, Int_t n)
Write array of Bool_t to buffer.
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition: TClass.cxx:3334
virtual void ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits)
read array of Float16_t from buffer
char name[80]
Definition: TGX11.cxx:109
const char * cnt
Definition: TXMLSetup.cxx:74
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual const char * GetName() const
Return name of this collection.
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1069
virtual void ReadUInt(UInt_t &i)
Reads UInt_t value from buffer.
virtual void ClassMember(const char *name, const char *typeName=0, Int_t arrsize1=-1, Int_t arrsize2=-1)
Method indicates name and typename of class member, which should be now streamed in custom streamer F...
const char * Data() const
Definition: TString.h:345
TVirtualStreamerInfo * fStreamerInfo
StreamerInfo used to derive these actions.