133 ClassImp(TBufferJSON);
135 enum { json_TArray = 100, json_TCollection = -130, json_TString = 110, json_stdstring = 120 };
143 class TArrayIndexProducer {
147 const char *fSepar{
nullptr};
151 Bool_t fIsArray{kFALSE};
154 TArrayIndexProducer(TStreamerElement *elem, Int_t arraylen,
const char *separ) : fSepar(separ)
156 Bool_t usearrayindx = elem && (elem->GetArrayDim() > 0);
157 Bool_t isloop = elem && ((elem->GetType() == TStreamerInfo::kStreamLoop) ||
158 (elem->GetType() == TStreamerInfo::kOffsetL + TStreamerInfo::kStreamLoop));
159 Bool_t usearraylen = (arraylen > (isloop ? 0 : 1));
161 if (usearrayindx && (arraylen > 0)) {
163 usearrayindx = kFALSE;
165 }
else if (arraylen != elem->GetArrayLength()) {
166 ::Error(
"TArrayIndexProducer",
"Problem with JSON coding of element %s type %d", elem->GetName(),
172 fTotalLen = elem->GetArrayLength();
173 fMaxIndex.Set(elem->GetArrayDim());
174 for (
int dim = 0; dim < elem->GetArrayDim(); dim++)
175 fMaxIndex[dim] = elem->GetMaxIndex(dim);
176 fIsArray = fTotalLen > 1;
177 }
else if (usearraylen) {
178 fTotalLen = arraylen;
180 fMaxIndex[0] = arraylen;
184 if (fMaxIndex.GetSize() > 0) {
185 fIndicies.Set(fMaxIndex.GetSize());
190 TArrayIndexProducer(TDataMember *member, Int_t extradim,
const char *separ) : fSepar(separ)
192 Int_t ndim = member->GetArrayDim();
201 for (
int dim = 0; dim < member->GetArrayDim(); dim++) {
202 fMaxIndex[dim] = member->GetMaxIndex(dim);
203 fTotalLen *= member->GetMaxIndex(dim);
207 fMaxIndex[ndim - 1] = extradim;
208 fTotalLen *= extradim;
211 fIsArray = fTotalLen > 1;
215 Int_t NumDimensions()
const {
return fIndicies.GetSize(); }
218 TArrayI &GetIndices() {
return fIndicies; };
221 Int_t TotalLength()
const {
return fTotalLen; }
223 Int_t ReduceDimension()
227 if (fMaxIndex.GetSize() == 0)
229 Int_t ndim = fMaxIndex.GetSize() - 1;
230 Int_t len = fMaxIndex[ndim];
233 fTotalLen = fTotalLen / len;
234 fIsArray = fTotalLen > 1;
238 Bool_t IsArray()
const {
return fIsArray; }
240 Bool_t IsDone()
const
243 return !IsArray() || (fCnt >= fTotalLen);
246 const char *GetBegin()
251 for (Int_t n = 0; n < fIndicies.GetSize(); ++n)
260 for (Int_t n = 0; n < fIndicies.GetSize(); ++n)
266 const char *NextSeparator()
268 if (++fCnt >= fTotalLen)
271 Int_t cnt = fIndicies.GetSize() - 1;
276 while ((cnt >= 0) && (cnt < fIndicies.GetSize())) {
277 if (fIndicies[cnt] >= fMaxIndex[cnt]) {
279 fIndicies[cnt--] = 0;
284 fRes.Append(fIndicies[cnt] == 0 ?
"[" : fSepar);
290 nlohmann::json *ExtractNode(nlohmann::json *topnode,
bool next =
true)
294 nlohmann::json *subnode = &((*((nlohmann::json *)topnode))[fIndicies[0]]);
295 for (
int k = 1; k < fIndicies.GetSize(); ++k)
296 subnode = &((*subnode)[fIndicies[k]]);
307 class TJSONStackObj :
public TObject {
311 Bool_t fFirst{kTRUE};
312 nlohmann::json::iterator fIter;
313 const char *fTypeTag{
nullptr};
314 nlohmann::json fValue;
315 nlohmann::json *GetStlNode(nlohmann::json *prnt)
318 return &(prnt->at(fIndx++));
321 nlohmann::json *json = &(prnt->at(fIndx));
322 if (!fFirst) fIndx++;
323 json = &(json->at(fFirst ?
"first" :
"second"));
330 if (fTypeTag && (fIter.key().compare(fTypeTag) == 0))
332 fValue = fIter.key();
335 fValue = fIter.value();
344 TStreamerInfo *fInfo{
nullptr};
345 TStreamerElement *fElem{
nullptr};
346 Bool_t fIsStreamerInfo{kFALSE};
347 Bool_t fIsElemOwner{kFALSE};
348 Bool_t fIsPostProcessed{kFALSE};
349 Bool_t fIsObjStarted{kFALSE};
350 Bool_t fAccObjects{kFALSE};
351 Bool_t fBase64{kFALSE};
352 std::vector<std::string> fValues;
354 int *fMemberPtr{
nullptr};
356 std::unique_ptr<TArrayIndexProducer> fIndx;
357 nlohmann::json *fNode{
nullptr};
358 std::unique_ptr<StlRead> fStlRead;
359 Version_t fClVersion{0};
361 TJSONStackObj() =
default;
369 Bool_t IsStreamerInfo()
const {
return fIsStreamerInfo; }
371 Bool_t IsStreamerElement()
const {
return !fIsStreamerInfo && fElem; }
373 void PushValue(TString &v)
375 fValues.emplace_back(v.Data());
379 void PushIntValue(Int_t v) { fValues.emplace_back(std::to_string(v)); }
383 const char *NextMemberSeparator()
385 return (!fMemberPtr || ((*fMemberPtr)++ > 0)) ?
"," :
"";
388 Bool_t IsJsonString() {
return fNode && fNode->is_string(); }
393 Int_t IsJsonArray(nlohmann::json *json =
nullptr,
const char *map_convert_type =
nullptr)
398 if (map_convert_type) {
399 if (!json->is_object())
return -1;
402 for (
auto it = json->begin(); it != json->end(); ++it) {
403 if ((strlen(map_convert_type)==0) || (it.key().compare(map_convert_type) != 0)) sz++;
409 if (json->is_array())
413 if (json->is_object() && (json->count(
"$arr") == 1))
414 return json->at(
"len").get<
int>();
421 auto res = std::stoi(fValues.back());
426 std::unique_ptr<TArrayIndexProducer> MakeReadIndexes()
428 if (!fElem || (fElem->GetType() <= TStreamerInfo::kOffsetL) ||
429 (fElem->GetType() >= TStreamerInfo::kOffsetL + 20) || (fElem->GetArrayDim() < 2))
432 auto indx = std::make_unique<TArrayIndexProducer>(fElem, -1,
"");
435 if (!indx->IsArray() || (indx->NumDimensions() < 2))
441 Bool_t IsStl()
const {
return fStlRead.get() !=
nullptr; }
443 Bool_t AssignStl(TClass *cl, Int_t map_convert,
const char *typename_tag)
445 fStlRead = std::make_unique<StlRead>();
446 fStlRead->fMap = map_convert;
447 if (map_convert == 2) {
448 if (!fNode->is_object()) {
449 ::Error(
"TJSONStackObj::AssignStl",
"when reading %s expecting JSON object", cl->GetName());
452 fStlRead->fIter = fNode->begin();
453 fStlRead->fTypeTag = typename_tag && (strlen(typename_tag) > 0) ? typename_tag :
nullptr;
455 if (!fNode->is_array() && !(fNode->is_object() && (fNode->count(
"$arr") == 1))) {
456 ::Error(
"TJSONStackObj::AssignStl",
"when reading %s expecting JSON array", cl->GetName());
463 nlohmann::json *GetStlNode()
465 return fStlRead ? fStlRead->GetStlNode(fNode) : fNode;
470 fStlRead.reset(
nullptr);
477 TBufferJSON::TBufferJSON(TBuffer::EMode mode)
478 : TBufferText(mode), fOutBuffer(), fOutput(nullptr), fValue(), fStack(), fSemicolon(
" : "), fArraySepar(
", "),
479 fNumericLocale(), fTypeNameTag(
"_typename")
481 fOutBuffer.Capacity(10000);
482 fValue.Capacity(1000);
483 fOutput = &fOutBuffer;
488 char *loc = setlocale(LC_NUMERIC,
nullptr);
489 if (loc && (strcmp(loc,
"C") != 0)) {
490 fNumericLocale = loc;
491 setlocale(LC_NUMERIC,
"C");
498 TBufferJSON::~TBufferJSON()
500 while (fStack.size() > 0)
503 if (fNumericLocale.Length() > 0)
504 setlocale(LC_NUMERIC, fNumericLocale.Data());
523 TString TBufferJSON::ConvertToJSON(
const TObject *obj, Int_t compact,
const char *member_name)
525 TClass *clActual =
nullptr;
526 void *ptr = (
void *)obj;
529 clActual = TObject::Class()->GetActualClass(obj);
531 clActual = TObject::Class();
532 else if (clActual != TObject::Class())
533 ptr = (
void *)((Long_t)obj - clActual->GetBaseClassOffset(TObject::Class()));
536 return ConvertToJSON(ptr, clActual, compact, member_name);
555 void TBufferJSON::SetCompact(
int level)
559 fCompact = level % 10;
560 if (fCompact >= kMapAsObject) {
561 fMapAsObject = kTRUE;
562 fCompact = fCompact % kMapAsObject;
564 fSemicolon = (fCompact >= kNoSpaces) ?
":" :
" : ";
565 fArraySepar = (fCompact >= kNoSpaces) ?
"," :
", ";
566 fArrayCompact = ((level / 10) % 10) * 10;
567 if ((((level / 100) % 10) * 100) == kSkipTypeInfo)
568 fTypeNameTag.Clear();
569 else if (fTypeNameTag.Length() == 0)
570 fTypeNameTag =
"_typename";
579 void TBufferJSON::SetTypenameTag(
const char *tag)
582 fTypeNameTag.Clear();
593 void TBufferJSON::SetTypeversionTag(
const char *tag)
596 fTypeVersionTag.Clear();
598 fTypeVersionTag = tag;
606 void TBufferJSON::SetSkipClassInfo(
const TClass *cl)
608 if (cl && (std::find(fSkipClasses.begin(), fSkipClasses.end(), cl) == fSkipClasses.end()))
609 fSkipClasses.emplace_back(cl);
615 Bool_t TBufferJSON::IsSkipClassInfo(
const TClass *cl)
const
617 return cl && (std::find(fSkipClasses.begin(), fSkipClasses.end(), cl) != fSkipClasses.end());
639 TString TBufferJSON::ConvertToJSON(
const void *obj,
const TClass *cl, Int_t compact,
const char *member_name)
641 TClass *clActual = obj ? cl->GetActualClass(obj) :
nullptr;
642 const void *actualStart = obj;
643 if (clActual && (clActual != cl)) {
644 actualStart = (
char *)obj - clActual->GetBaseClassOffset(cl);
648 clActual =
const_cast<TClass *
>(cl);
651 if (member_name && actualStart) {
652 TRealData *rdata = clActual->GetRealData(member_name);
653 TDataMember *member = rdata ? rdata->GetDataMember() :
nullptr;
655 TIter iter(clActual->GetListOfRealData());
656 while ((rdata = dynamic_cast<TRealData *>(iter())) !=
nullptr) {
657 member = rdata->GetDataMember();
658 if (member && strcmp(member->GetName(), member_name) == 0)
666 if (member->GetArrayIndex() != 0) {
667 TRealData *idata = clActual->GetRealData(member->GetArrayIndex());
668 TDataMember *imember = idata ? idata->GetDataMember() :
nullptr;
669 if (imember && (strcmp(imember->GetTrueTypeName(),
"int") == 0)) {
670 arraylen = *((
int *)((
char *)actualStart + idata->GetThisOffset()));
674 void *ptr = (
char *)actualStart + rdata->GetThisOffset();
675 if (member->IsaPointer())
676 ptr = *((
char **)ptr);
678 return TBufferJSON::ConvertToJSON(ptr, member, compact, arraylen);
683 buf.SetCompact(compact);
685 return buf.StoreObject(actualStart, clActual);
701 TString TBufferJSON::StoreObject(
const void *obj,
const TClass *cl)
709 JsonWriteObject(obj, cl);
713 Error(
"StoreObject",
"Can not store object into TBuffer for reading");
716 return fOutBuffer.Length() ? fOutBuffer : fValue;
725 TString TBufferJSON::ConvertToJSON(
const void *ptr, TDataMember *member, Int_t compact, Int_t arraylen)
728 return TString(
"null");
730 Bool_t stlstring = !strcmp(member->GetTrueTypeName(),
"string");
732 Int_t isstl = member->IsSTLContainer();
734 TClass *mcl = member->IsBasic() ?
nullptr : gROOT->GetClass(member->GetTypeName());
736 if (mcl && (mcl != TString::Class()) && !stlstring && !isstl && (mcl->GetBaseClassOffset(TArray::Class()) != 0) &&
737 (arraylen <= 0) && (member->GetArrayDim() == 0))
738 return TBufferJSON::ConvertToJSON(ptr, mcl, compact);
742 buf.SetCompact(compact);
744 return buf.JsonWriteMember(ptr, member, mcl, arraylen);
752 Int_t TBufferJSON::ExportToFile(
const char *filename,
const TObject *obj,
const char *option)
754 if (!obj || !filename || (*filename == 0))
757 Int_t compact = strstr(filename,
".json.gz") ? 3 : 0;
758 if (option && (*option >=
'0') && (*option <=
'3'))
759 compact = TString(option).Atoi();
761 TString json = TBufferJSON::ConvertToJSON(obj, compact);
763 std::ofstream ofs(filename);
765 if (strstr(filename,
".json.gz")) {
766 const char *objbuf = json.Data();
767 Long_t objlen = json.Length();
769 unsigned long objcrc = R__crc32(0, NULL, 0);
770 objcrc = R__crc32(objcrc, (
const unsigned char *)objbuf, objlen);
773 Int_t buflen = 10 + objlen + 8;
777 char *buffer = (
char *)malloc(buflen);
781 char *bufcur = buffer;
797 memcpy(dummy, bufcur - 6, 6);
800 unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, (
char *)objbuf, objlen);
802 memcpy(bufcur - 6, dummy, 6);
804 bufcur += (ziplen - 6);
806 *bufcur++ = objcrc & 0xff;
807 *bufcur++ = (objcrc >> 8) & 0xff;
808 *bufcur++ = (objcrc >> 16) & 0xff;
809 *bufcur++ = (objcrc >> 24) & 0xff;
811 *bufcur++ = objlen & 0xff;
812 *bufcur++ = (objlen >> 8) & 0xff;
813 *bufcur++ = (objlen >> 16) & 0xff;
814 *bufcur++ = (objlen >> 24) & 0xff;
816 ofs.write(buffer, bufcur - buffer);
825 return json.Length();
832 Int_t TBufferJSON::ExportToFile(
const char *filename,
const void *obj,
const TClass *cl,
const char *option)
834 if (!obj || !cl || !filename || (*filename == 0))
837 Int_t compact = strstr(filename,
".json.gz") ? 3 : 0;
838 if (option && (*option >=
'0') && (*option <=
'3'))
839 compact = TString(option).Atoi();
841 TString json = TBufferJSON::ConvertToJSON(obj, cl, compact);
843 std::ofstream ofs(filename);
845 if (strstr(filename,
".json.gz")) {
846 const char *objbuf = json.Data();
847 Long_t objlen = json.Length();
849 unsigned long objcrc = R__crc32(0, NULL, 0);
850 objcrc = R__crc32(objcrc, (
const unsigned char *)objbuf, objlen);
853 Int_t buflen = 10 + objlen + 8;
857 char *buffer = (
char *)malloc(buflen);
861 char *bufcur = buffer;
877 memcpy(dummy, bufcur - 6, 6);
880 unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, (
char *)objbuf, objlen);
882 memcpy(bufcur - 6, dummy, 6);
884 bufcur += (ziplen - 6);
886 *bufcur++ = objcrc & 0xff;
887 *bufcur++ = (objcrc >> 8) & 0xff;
888 *bufcur++ = (objcrc >> 16) & 0xff;
889 *bufcur++ = (objcrc >> 24) & 0xff;
891 *bufcur++ = objlen & 0xff;
892 *bufcur++ = (objlen >> 8) & 0xff;
893 *bufcur++ = (objlen >> 16) & 0xff;
894 *bufcur++ = (objlen >> 24) & 0xff;
896 ofs.write(buffer, bufcur - buffer);
905 return json.Length();
912 TObject *TBufferJSON::ConvertFromJSON(
const char *str)
914 TClass *cl =
nullptr;
915 void *obj = ConvertFromJSONAny(str, &cl);
920 Int_t delta = cl->GetBaseClassOffset(TObject::Class());
927 return (TObject *)(((
char *)obj) + delta);
935 void *TBufferJSON::ConvertFromJSONAny(
const char *str, TClass **cl)
937 TBufferJSON buf(TBuffer::kRead);
939 return buf.RestoreObject(str, cl);
947 void *TBufferJSON::RestoreObject(
const char *json_str, TClass **cl)
952 nlohmann::json docu = nlohmann::json::parse(json_str);
954 if (docu.is_null() || (!docu.is_object() && !docu.is_array()))
957 TClass *objClass =
nullptr;
968 void *obj = JsonReadObject(
nullptr, objClass, cl);
978 void *TBufferJSON::ConvertFromJSONChecked(
const char *str,
const TClass *expectedClass)
983 TClass *resClass =
const_cast<TClass *
>(expectedClass);
985 void *res = ConvertFromJSONAny(str, &resClass);
987 if (!res || !resClass)
990 if (resClass == expectedClass)
993 Int_t offset = resClass->GetBaseClassOffset(expectedClass);
995 ::Error(
"TBufferJSON::ConvertFromJSONChecked",
"expected class %s is not base for read class %s",
996 expectedClass->GetName(), resClass->GetName());
997 resClass->Destructor(res);
1001 return (
char *)res - offset;
1008 TString TBufferJSON::JsonWriteMember(
const void *ptr, TDataMember *member, TClass *memberClass, Int_t arraylen)
1014 Info(
"JsonWriteMember",
"Write member %s type %s ndim %d", member->GetName(), member->GetTrueTypeName(),
1015 member->GetArrayDim());
1017 Int_t tid = member->GetDataType() ? member->GetDataType()->GetType() : kNoType_t;
1018 if (strcmp(member->GetTrueTypeName(),
"const char*") == 0)
1020 else if (!member->IsBasic() || (tid == kOther_t) || (tid == kVoid_t))
1024 return (tid == kCharStar) ?
"\"\"" :
"null";
1029 if (tid != kNoType_t) {
1031 TArrayIndexProducer indx(member, arraylen, fArraySepar.Data());
1035 if (indx.IsArray() && (tid == kChar_t))
1036 shift = indx.ReduceDimension();
1038 char *ppp = (
char *)ptr;
1041 fOutBuffer.Append(indx.GetBegin());
1049 JsonWriteConstChar((Char_t *)ppp, shift);
1051 JsonWriteBasic(*((Char_t *)ppp));
1053 case kShort_t: JsonWriteBasic(*((Short_t *)ppp));
break;
1054 case kInt_t: JsonWriteBasic(*((Int_t *)ppp));
break;
1055 case kLong_t: JsonWriteBasic(*((Long_t *)ppp));
break;
1056 case kFloat_t: JsonWriteBasic(*((Float_t *)ppp));
break;
1057 case kCounter: JsonWriteBasic(*((Int_t *)ppp));
break;
1058 case kCharStar: JsonWriteConstChar((Char_t *)ppp);
break;
1059 case kDouble_t: JsonWriteBasic(*((Double_t *)ppp));
break;
1060 case kDouble32_t: JsonWriteBasic(*((Double_t *)ppp));
break;
1061 case kchar: JsonWriteBasic(*((
char *)ppp));
break;
1062 case kUChar_t: JsonWriteBasic(*((UChar_t *)ppp));
break;
1063 case kUShort_t: JsonWriteBasic(*((UShort_t *)ppp));
break;
1064 case kUInt_t: JsonWriteBasic(*((UInt_t *)ppp));
break;
1065 case kULong_t: JsonWriteBasic(*((ULong_t *)ppp));
break;
1066 case kBits: JsonWriteBasic(*((UInt_t *)ppp));
break;
1067 case kLong64_t: JsonWriteBasic(*((Long64_t *)ppp));
break;
1068 case kULong64_t: JsonWriteBasic(*((ULong64_t *)ppp));
break;
1069 case kBool_t: JsonWriteBasic(*((Bool_t *)ppp));
break;
1070 case kFloat16_t: JsonWriteBasic(*((Float_t *)ppp));
break;
1072 case kVoid_t:
break;
1075 fOutBuffer.Append(fValue);
1077 fOutBuffer.Append(indx.NextSeparator());
1079 ppp += shift * member->GetUnitSize();
1081 }
while (!indx.IsDone());
1083 fValue = fOutBuffer;
1085 }
else if (memberClass == TString::Class()) {
1086 TString *str = (TString *)ptr;
1087 JsonWriteConstChar(str ? str->Data() :
nullptr);
1088 }
else if ((member->IsSTLContainer() == ROOT::kSTLvector) || (member->IsSTLContainer() == ROOT::kSTLlist) ||
1089 (member->IsSTLContainer() == ROOT::kSTLforwardlist)) {
1092 memberClass->Streamer((
void *)ptr, *
this);
1099 }
else if (memberClass && memberClass->GetBaseClassOffset(TArray::Class()) == 0) {
1100 TArray *arr = (TArray *)ptr;
1101 if (arr && (arr->GetSize() > 0)) {
1102 arr->Streamer(*
this);
1104 if (Stack()->fValues.size() > 1) {
1105 Warning(
"TBufferJSON",
"When streaming TArray, more than 1 object in the stack, use second item");
1106 fValue = Stack()->fValues[1].c_str();
1110 }
else if (memberClass && !strcmp(memberClass->GetName(),
"string")) {
1112 memberClass->Streamer((
void *)ptr, *
this);
1116 if (fValue.Length())
1119 if (!memberClass || (member->GetArrayDim() > 0) || (arraylen > 0))
1120 return "<not supported>";
1122 return TBufferJSON::ConvertToJSON(ptr, memberClass);
1128 TJSONStackObj *TBufferJSON::PushStack(Int_t inclevel,
void *readnode)
1130 auto next =
new TJSONStackObj();
1131 next->fLevel = inclevel;
1133 next->fNode = (nlohmann::json *)readnode;
1134 }
else if (fStack.size() > 0) {
1135 auto prev = Stack();
1136 next->fLevel += prev->fLevel;
1137 next->fMemberPtr = prev->fMemberPtr;
1139 fStack.emplace_back(next);
1146 TJSONStackObj *TBufferJSON::PopStack()
1148 if (fStack.size() > 0)
1151 return fStack.size() > 0 ? fStack.back().get() :
nullptr;
1157 void TBufferJSON::AppendOutput(
const char *line0,
const char *line1)
1160 fOutput->Append(line0);
1164 fOutput->Append(
"\n");
1166 if (strlen(line1) > 0) {
1168 if (Stack()->fLevel > 0)
1169 fOutput->Append(
' ', Stack()->fLevel);
1171 fOutput->Append(line1);
1179 TJSONStackObj *TBufferJSON::JsonStartObjectWrite(
const TClass *obj_class, TStreamerInfo *info)
1181 auto stack = PushStack(2);
1184 stack->fMemberPtr = &stack->fMemberCnt;
1186 if ((fTypeNameTag.Length() > 0) && !IsSkipClassInfo(obj_class)) {
1188 AppendOutput(
"{",
"\"");
1189 AppendOutput(fTypeNameTag.Data());
1191 AppendOutput(fSemicolon.Data());
1193 AppendOutput(obj_class->GetName());
1195 if (fTypeVersionTag.Length() > 0) {
1196 AppendOutput(stack->NextMemberSeparator(),
"\"");
1197 AppendOutput(fTypeVersionTag.Data());
1199 AppendOutput(fSemicolon.Data());
1200 AppendOutput(Form(
"%d", (
int)(info ? info->GetClassVersion() : obj_class->GetClassVersion())));
1203 stack->fMemberCnt = 0;
1213 void TBufferJSON::JsonStartElement(
const TStreamerElement *elem,
const TClass *base_class)
1215 const char *elem_name =
nullptr;
1216 Int_t special_kind = JsonSpecialClass(base_class);
1218 switch (special_kind) {
1221 elem_name = elem->GetName();
1223 case TClassEdit::kVector: elem_name =
"fVector";
break;
1224 case TClassEdit::kList: elem_name =
"fList";
break;
1225 case TClassEdit::kForwardlist: elem_name =
"fForwardlist";
break;
1226 case TClassEdit::kDeque: elem_name =
"fDeque";
break;
1227 case TClassEdit::kMap: elem_name =
"fMap";
break;
1228 case TClassEdit::kMultiMap: elem_name =
"fMultiMap";
break;
1229 case TClassEdit::kSet: elem_name =
"fSet";
break;
1230 case TClassEdit::kMultiSet: elem_name =
"fMultiSet";
break;
1231 case TClassEdit::kUnorderedSet: elem_name =
"fUnorderedSet";
break;
1232 case TClassEdit::kUnorderedMultiSet: elem_name =
"fUnorderedMultiSet";
break;
1233 case TClassEdit::kUnorderedMap: elem_name =
"fUnorderedMap";
break;
1234 case TClassEdit::kUnorderedMultiMap: elem_name =
"fUnorderedMultiMap";
break;
1235 case TClassEdit::kBitSet: elem_name =
"fBitSet";
break;
1236 case json_TArray: elem_name =
"fArray";
break;
1238 case json_stdstring: elem_name =
"fString";
break;
1245 nlohmann::json *json = Stack()->fNode;
1247 if (json->count(elem_name) != 1) {
1248 Error(
"JsonStartElement",
"Missing JSON structure for element %s", elem_name);
1250 Stack()->fNode = &((*json)[elem_name]);
1251 if (special_kind == json_TArray) {
1252 Int_t len = Stack()->IsJsonArray();
1253 Stack()->PushIntValue(len > 0 ? len : 0);
1255 Error(
"JsonStartElement",
"Missing array when reading TArray class for element %s", elem->GetName());
1257 if ((gDebug > 1) && base_class)
1258 Info(
"JsonStartElement",
"Reading baseclass %s from element %s", base_class->GetName(), elem_name);
1262 AppendOutput(Stack()->NextMemberSeparator(),
"\"");
1263 AppendOutput(elem_name);
1265 AppendOutput(fSemicolon.Data());
1271 void TBufferJSON::JsonDisablePostprocessing()
1273 Stack()->fIsPostProcessed = kTRUE;
1280 Int_t TBufferJSON::JsonSpecialClass(
const TClass *cl)
const
1285 Bool_t isarray = strncmp(
"TArray", cl->GetName(), 6) == 0;
1287 isarray = (
const_cast<TClass *
>(cl))->GetBaseClassOffset(TArray::Class()) == 0;
1292 if ((const_cast<TClass *>(cl))->GetBaseClassOffset(TCollection::Class()) == 0)
1293 return json_TCollection;
1296 if (cl == TString::Class())
1297 return json_TString;
1299 bool isstd = TClassEdit::IsStdClass(cl->GetName());
1300 int isstlcont(ROOT::kNotSTL);
1302 isstlcont = cl->GetCollectionType();
1307 if (isstd && !strcmp(cl->GetName(),
"string"))
1308 return json_stdstring;
1318 void TBufferJSON::JsonWriteObject(
const void *obj,
const TClass *cl, Bool_t check_map)
1324 Info(
"JsonWriteObject",
"Object %p class %s check_map %s", obj, cl ? cl->GetName() :
"null",
1325 check_map ?
"true" :
"false");
1327 Int_t special_kind = JsonSpecialClass(cl), map_convert{0};
1329 TString fObjectOutput, *fPrevOutput{
nullptr};
1331 TJSONStackObj *stack = Stack();
1333 if (stack && stack->fAccObjects && ((fValue.Length() > 0) || (stack->fValues.size() > 0))) {
1336 if (fValue.Length() > 0)
1337 stack->PushValue(fValue);
1340 fPrevOutput = fOutput;
1341 fOutput = &fObjectOutput;
1342 }
else if ((special_kind <= 0) || (special_kind > json_TArray)) {
1344 JsonDisablePostprocessing();
1345 }
else if ((special_kind == TClassEdit::kMap) || (special_kind == TClassEdit::kMultiMap) ||
1346 (special_kind == TClassEdit::kUnorderedMap) || (special_kind == TClassEdit::kUnorderedMultiMap)) {
1348 if ((fMapAsObject && (fStack.size()==1)) || (stack && stack->fElem && strstr(stack->fElem->GetTitle(),
"JSON_object")))
1355 AppendOutput(
"null");
1359 if (special_kind <= 0) {
1362 Long64_t refid = GetObjectTag(obj);
1367 AppendOutput(Form(
"{\"$ref\":%u}", (
unsigned)(refid - 1)));
1370 MapObject(obj, cl, fJsonrCnt + 1);
1375 stack = JsonStartObjectWrite(cl);
1377 }
else if (map_convert == 2) {
1381 Long64_t refid = GetObjectTag(obj);
1383 fValue.Form(
"{\"$ref\":%u}", (
unsigned)(refid - 1));
1386 MapObject(obj, cl, fJsonrCnt + 1);
1390 stack = PushStack(0);
1394 bool base64 = ((special_kind == TClassEdit::kVector) && stack && stack->fElem && strstr(stack->fElem->GetTitle(),
"JSON_base64"));
1398 stack = PushStack(0);
1400 stack->fBase64 = base64;
1404 Info(
"JsonWriteObject",
"Starting object %p write for class: %s", obj, cl->GetName());
1406 stack->fAccObjects = special_kind < ROOT::kSTLend;
1408 if (special_kind == json_TCollection)
1409 JsonWriteCollection((TCollection *)obj, cl);
1411 (const_cast<TClass *>(cl))->Streamer((
void *)obj, *
this);
1414 Info(
"JsonWriteObject",
"Done object %p write for class: %s", obj, cl->GetName());
1416 if (special_kind == json_TArray) {
1417 if (stack->fValues.size() != 1)
1418 Error(
"JsonWriteObject",
"Problem when writing array");
1419 stack->fValues.clear();
1420 }
else if ((special_kind == json_TString) || (special_kind == json_stdstring)) {
1421 if (stack->fValues.size() > 2)
1422 Error(
"JsonWriteObject",
"Problem when writing TString or std::string");
1423 stack->fValues.clear();
1424 AppendOutput(fValue.Data());
1426 }
else if ((special_kind > 0) && (special_kind < ROOT::kSTLend)) {
1429 if (map_convert == 2) {
1432 if (!stack->fValues.empty() && (fValue.Length() > 0))
1433 stack->PushValue(fValue);
1435 const char *separ = (fCompact < 2) ?
", " :
",";
1436 const char *semi = (fCompact < 2) ?
": " :
":";
1440 if (fTypeNameTag.Length() > 0) {
1441 fValue.Append(
"\"");
1442 fValue.Append(fTypeNameTag);
1443 fValue.Append(
"\"");
1444 fValue.Append(semi);
1445 fValue.Append(
"\"");
1446 fValue.Append(cl->GetName());
1447 fValue.Append(
"\"");
1450 for (Int_t k = 1; k < (int)stack->fValues.size() - 1; k += 2) {
1452 fValue.Append(separ);
1454 fValue.Append(stack->fValues[k].c_str());
1455 fValue.Append(semi);
1456 fValue.Append(stack->fValues[k + 1].c_str());
1459 stack->fValues.clear();
1460 }
else if (stack->fValues.empty()) {
1463 Error(
"JsonWriteObject",
"With empty stack fValue!=0");
1467 auto size = std::stoi(stack->fValues[0]);
1469 bool trivial_format =
false;
1471 if ((stack->fValues.size() == 1) && ((size > 1) || ((fValue.Length() > 1) && (fValue[0]==
'[')))) {
1473 const auto proxy = cl->GetCollectionProxy();
1474 TClass *value_class = proxy ? proxy->GetValueClass() :
nullptr;
1475 if (value_class && TClassEdit::IsStdClass(value_class->GetName()) && (value_class->GetCollectionType() != ROOT::kNotSTL))
1476 trivial_format =
false;
1478 trivial_format =
true;
1481 if (trivial_format) {
1483 stack->fValues.clear();
1484 if (fValue.Length() == 0) {
1485 Error(
"JsonWriteObject",
"Empty value when it should contain something");
1490 const char *separ =
"[";
1492 if (fValue.Length() > 0)
1493 stack->PushValue(fValue);
1495 if ((size * 2 == (
int) stack->fValues.size() - 1) && (map_convert > 0)) {
1498 TString pairtype = cl->GetName();
1499 if (pairtype.Index(
"unordered_map<") == 0)
1500 pairtype.Replace(0, 14,
"pair<");
1501 else if (pairtype.Index(
"unordered_multimap<") == 0)
1502 pairtype.Replace(0, 19,
"pair<");
1503 else if (pairtype.Index(
"multimap<") == 0)
1504 pairtype.Replace(0, 9,
"pair<");
1505 else if (pairtype.Index(
"map<") == 0)
1506 pairtype.Replace(0, 4,
"pair<");
1509 if (fTypeNameTag.Length() == 0)
1512 pairtype = TString(
"\"") + pairtype + TString(
"\"");
1513 for (Int_t k = 1; k < (int) stack->fValues.size() - 1; k += 2) {
1514 fValue.Append(separ);
1515 separ = fArraySepar.Data();
1518 fValue.Append(
"\"$pair\"");
1519 fValue.Append(fSemicolon);
1520 fValue.Append(pairtype.Data());
1521 fValue.Append(fArraySepar);
1522 fValue.Append(
"\"first\"");
1523 fValue.Append(fSemicolon);
1524 fValue.Append(stack->fValues[k].c_str());
1525 fValue.Append(fArraySepar);
1526 fValue.Append(
"\"second\"");
1527 fValue.Append(fSemicolon);
1528 fValue.Append(stack->fValues[k + 1].c_str());
1533 for (Int_t k = 1; k < (int) stack->fValues.size(); k++) {
1534 fValue.Append(separ);
1535 separ = fArraySepar.Data();
1536 fValue.Append(stack->fValues[k].c_str());
1541 stack->fValues.clear();
1547 PerformPostProcessing(stack, cl);
1549 if ((special_kind == 0) && (!stack->fValues.empty() || (fValue.Length() > 0))) {
1551 Info(
"JsonWriteObject",
"Create blob value for class %s", cl->GetName());
1553 AppendOutput(fArraySepar.Data(),
"\"_blob\"");
1554 AppendOutput(fSemicolon.Data());
1556 const char *separ =
"[";
1558 for (
auto &elem: stack->fValues) {
1559 AppendOutput(separ);
1560 separ = fArraySepar.Data();
1561 AppendOutput(elem.c_str());
1564 if (fValue.Length() > 0) {
1565 AppendOutput(separ);
1566 AppendOutput(fValue.Data());
1572 stack->fValues.clear();
1577 if ((special_kind <= 0))
1578 AppendOutput(
nullptr,
"}");
1583 fOutput = fPrevOutput;
1585 if ((special_kind <= 0) || (special_kind > json_TArray))
1586 fValue = fObjectOutput;
1587 else if (fObjectOutput.Length() != 0)
1588 Error(
"JsonWriteObject",
"Non-empty object output for special class %s", cl->GetName());
1595 void TBufferJSON::JsonWriteCollection(TCollection *col,
const TClass *)
1597 AppendOutput(Stack()->NextMemberSeparator(),
"\"name\"");
1598 AppendOutput(fSemicolon.Data());
1600 AppendOutput(col->GetName());
1602 AppendOutput(Stack()->NextMemberSeparator(),
"\"arr\"");
1603 AppendOutput(fSemicolon.Data());
1608 bool islist = col->InheritsFrom(TList::Class());
1609 TMap *map =
nullptr;
1610 if (col->InheritsFrom(TMap::Class()))
1611 map = dynamic_cast<TMap *>(col);
1621 Bool_t first = kTRUE;
1622 while ((obj = iter()) !=
nullptr) {
1624 AppendOutput(fArraySepar.Data());
1628 AppendOutput(
"{",
"\"$pair\"");
1629 AppendOutput(fSemicolon.Data());
1630 AppendOutput(
"\"TPair\"");
1631 AppendOutput(fArraySepar.Data(),
"\"first\"");
1632 AppendOutput(fSemicolon.Data());
1635 WriteObjectAny(obj, TObject::Class());
1638 AppendOutput(fArraySepar.Data(),
"\"second\"");
1639 AppendOutput(fSemicolon.Data());
1640 WriteObjectAny(map->GetValue(obj), TObject::Class());
1641 AppendOutput(
"",
"}");
1646 sopt.Append(fArraySepar.Data());
1648 sopt.Append(iter.GetOption());
1659 AppendOutput(Stack()->NextMemberSeparator(),
"\"opt\"");
1660 AppendOutput(fSemicolon.Data());
1661 AppendOutput(sopt.Data());
1669 void TBufferJSON::JsonReadCollection(TCollection *col,
const TClass *)
1674 TList *lst =
nullptr;
1675 TMap *map =
nullptr;
1676 TClonesArray *clones =
nullptr;
1677 if (col->InheritsFrom(TList::Class()))
1678 lst = dynamic_cast<TList *>(col);
1679 else if (col->InheritsFrom(TMap::Class()))
1680 map = dynamic_cast<TMap *>(col);
1681 else if (col->InheritsFrom(TClonesArray::Class()))
1682 clones = dynamic_cast<TClonesArray *>(col);
1684 nlohmann::json *json = Stack()->fNode;
1686 std::string name = json->at(
"name");
1687 col->SetName(name.c_str());
1689 nlohmann::json &arr = json->at(
"arr");
1690 int size = arr.size();
1692 for (
int n = 0; n < size; ++n) {
1693 nlohmann::json *subelem = &arr.at(n);
1696 subelem = &subelem->at(
"first");
1698 PushStack(0, subelem);
1700 TClass *readClass =
nullptr, *objClass =
nullptr;
1701 void *subobj =
nullptr;
1705 if (!clones->GetClass() || (clones->GetSize() == 0)) {
1706 if (fTypeNameTag.Length() > 0) {
1707 clones->SetClass(subelem->at(fTypeNameTag.Data()).get<std::string>().c_str(), size);
1709 Error(
"JsonReadCollection",
1710 "Cannot detect class name for TClonesArray - typename tag not configured");
1713 }
else if (size > clones->GetSize()) {
1714 Error(
"JsonReadCollection",
"TClonesArray size %d smaller than required %d", clones->GetSize(), size);
1718 objClass = clones->GetClass();
1719 subobj = clones->ConstructedAt(n);
1722 subobj = JsonReadObject(subobj, objClass, &readClass);
1729 if (!subobj || !readClass) {
1731 }
else if (readClass->GetBaseClassOffset(TObject::Class()) != 0) {
1732 Error(
"JsonReadCollection",
"Try to add object %s not derived from TObject", readClass->GetName());
1736 TObject *tobj =
static_cast<TObject *
>(subobj);
1739 PushStack(0, &arr.at(n).at(
"second"));
1741 readClass =
nullptr;
1742 void *subobj2 = JsonReadObject(
nullptr,
nullptr, &readClass);
1746 if (!subobj2 || !readClass) {
1748 }
else if (readClass->GetBaseClassOffset(TObject::Class()) != 0) {
1749 Error(
"JsonReadCollection",
"Try to add object %s not derived from TObject", readClass->GetName());
1753 map->Add(tobj, static_cast<TObject *>(subobj2));
1755 std::string opt = json->at(
"opt").at(n).get<std::string>();
1756 lst->Add(tobj, opt.c_str());
1767 void *TBufferJSON::JsonReadObject(
void *obj,
const TClass *objClass, TClass **readClass)
1770 *readClass =
nullptr;
1772 TJSONStackObj *stack = Stack();
1774 Bool_t process_stl = stack->IsStl();
1775 nlohmann::json *json = stack->GetStlNode();
1778 if (json->is_null())
1781 Int_t special_kind = JsonSpecialClass(objClass);
1784 if (json->is_object() && (json->size() == 1) && (json->find(
"$ref") != json->end())) {
1785 unsigned refid = json->at(
"$ref").get<
unsigned>();
1787 void *ref_obj =
nullptr;
1788 TClass *ref_cl =
nullptr;
1790 GetMappedObject(refid + 1, ref_obj, ref_cl);
1792 if (!ref_obj || !ref_cl) {
1793 Error(
"JsonReadObject",
"Fail to find object for reference %u", refid);
1798 *readClass = ref_cl;
1801 Info(
"JsonReadObject",
"Extract object reference %u %p cl:%s expects:%s", refid, ref_obj, ref_cl->GetName(),
1802 (objClass ? objClass->GetName() :
"---"));
1808 if ((special_kind == json_stdstring) || (special_kind == json_TString)) {
1810 obj = objClass->New();
1813 Info(
"JsonReadObject",
"Read string from %s", json->dump().c_str());
1815 if (special_kind == json_stdstring)
1816 *((std::string *)obj) = json->get<std::string>();
1818 *((TString *)obj) = json->get<std::string>().c_str();
1821 *readClass =
const_cast<TClass *
>(objClass);
1826 Bool_t isBase = (stack->fElem && objClass) ? stack->fElem->IsBase() : kFALSE;
1828 if (isBase && (!obj || !objClass)) {
1829 Error(
"JsonReadObject",
"No object when reading base class");
1833 Int_t map_convert = 0;
1834 if ((special_kind == TClassEdit::kMap) || (special_kind == TClassEdit::kMultiMap) ||
1835 (special_kind == TClassEdit::kUnorderedMap) || (special_kind == TClassEdit::kUnorderedMultiMap)) {
1836 map_convert = json->is_object() ? 2 : 1;
1842 stack = PushStack(0, json);
1844 TClass *jsonClass =
nullptr;
1845 Int_t jsonClassVersion = 0;
1847 if ((special_kind == json_TArray) || ((special_kind > 0) && (special_kind < ROOT::kSTLend))) {
1849 jsonClass =
const_cast<TClass *
>(objClass);
1852 obj = jsonClass->New();
1854 Int_t len = stack->IsJsonArray(json, map_convert == 2 ? fTypeNameTag.Data() :
nullptr);
1856 stack->PushIntValue(len > 0 ? len : 0);
1859 Error(
"JsonReadObject",
"Not array when expecting such %s", json->dump().c_str());
1862 Info(
"JsonReadObject",
"Reading special kind %d %s ptr %p", special_kind, objClass->GetName(), obj);
1864 }
else if (isBase) {
1867 jsonClass =
const_cast<TClass *
>(objClass);
1870 Info(
"JsonReadObject",
"Reading baseclass %s ptr %p", objClass->GetName(), obj);
1873 if ((fTypeNameTag.Length() > 0) && (json->count(fTypeNameTag.Data()) > 0)) {
1874 std::string clname = json->at(fTypeNameTag.Data()).get<std::string>();
1875 jsonClass = TClass::GetClass(clname.c_str());
1877 Error(
"JsonReadObject",
"Cannot find class %s", clname.c_str());
1880 jsonClass =
const_cast<TClass *
>(objClass);
1889 if ((fTypeVersionTag.Length() > 0) && (json->count(fTypeVersionTag.Data()) > 0))
1890 jsonClassVersion = json->at(fTypeVersionTag.Data()).get<int>();
1892 if (objClass && (jsonClass != objClass)) {
1893 Error(
"JsonReadObject",
"Class mismatch between provided %s and in JSON %s", objClass->GetName(),
1894 jsonClass->GetName());
1898 obj = jsonClass->New();
1901 Info(
"JsonReadObject",
"Reading object of class %s refid %u ptr %p", jsonClass->GetName(), fJsonrCnt, obj);
1904 special_kind = JsonSpecialClass(jsonClass);
1907 MapObject(obj, jsonClass, ++fJsonrCnt);
1914 if ((jsonClass == TObject::Class()) || (jsonClass == TRef::Class())) {
1917 JsonReadTObjectMembers((TObject *)obj, json);
1919 }
else if (special_kind == json_TCollection) {
1921 JsonReadCollection((TCollection *)obj, jsonClass);
1925 Bool_t do_read = kTRUE;
1928 if ((special_kind > 0) && (special_kind < ROOT::kSTLend))
1929 do_read = stack->AssignStl(jsonClass, map_convert, fTypeNameTag.Data());
1932 stack->fClVersion = jsonClassVersion ? jsonClassVersion : jsonClass->GetClassVersion();
1935 Info(
"JsonReadObject",
"Calling streamer of class %s", jsonClass->GetName());
1937 if (isBase && (special_kind == 0))
1938 Error(
"JsonReadObject",
"Should not be used for reading of base class %s", jsonClass->GetName());
1941 jsonClass->Streamer((
void *)obj, *
this);
1943 stack->fClVersion = 0;
1953 Info(
"JsonReadObject",
"Reading object of class %s done", jsonClass->GetName());
1956 *readClass = jsonClass;
1965 void TBufferJSON::JsonReadTObjectMembers(TObject *tobj,
void *node)
1967 nlohmann::json *json = node ? (nlohmann::json *)node : Stack()->fNode;
1969 UInt_t uid = json->at(
"fUniqueID").get<
unsigned>();
1970 UInt_t bits = json->at(
"fBits").get<
unsigned>();
1973 tobj->SetUniqueID(uid);
1975 static auto tobj_fbits_offset = TObject::Class()->GetDataMemberOffset(
"fBits");
1978 if (tobj_fbits_offset > 0) {
1979 UInt_t *fbits = (UInt_t *) ((
char* ) tobj + tobj_fbits_offset);
1980 *fbits = (*fbits & (TObject::kIsOnHeap | TObject::kNotDeleted)) | bits;
1990 void TBufferJSON::IncrementLevel(TVirtualStreamerInfo *info)
1993 Info(
"IncrementLevel",
"Class: %s", (info ? info->GetClass()->GetName() :
"custom"));
1995 WorkWithClass((TStreamerInfo *)info);
2001 void TBufferJSON::WorkWithClass(TStreamerInfo *sinfo,
const TClass *cl)
2004 cl = sinfo->GetClass();
2010 Info(
"WorkWithClass",
"Class: %s", cl->GetName());
2012 TJSONStackObj *stack = Stack();
2015 stack = PushStack(0, stack->fNode);
2016 }
else if (stack && stack->IsStreamerElement() && !stack->fIsObjStarted &&
2017 ((stack->fElem->GetType() == TStreamerInfo::kObject) ||
2018 (stack->fElem->GetType() == TStreamerInfo::kAny))) {
2020 stack->fIsObjStarted = kTRUE;
2024 stack = JsonStartObjectWrite(cl, sinfo);
2026 stack = PushStack(0);
2029 stack->fInfo = sinfo;
2030 stack->fIsStreamerInfo = kTRUE;
2037 void TBufferJSON::DecrementLevel(TVirtualStreamerInfo *info)
2040 Info(
"DecrementLevel",
"Class: %s", (info ? info->GetClass()->GetName() :
"custom"));
2042 TJSONStackObj *stack = Stack();
2044 if (stack->IsStreamerElement()) {
2048 Info(
"DecrementLevel",
" Perform post-processing elem: %s", stack->fElem->GetName());
2050 PerformPostProcessing(stack);
2056 if (stack->fInfo != (TStreamerInfo *)info)
2057 Error(
"DecrementLevel",
" Mismatch of streamer info");
2062 Info(
"DecrementLevel",
"Class: %s done", (info ? info->GetClass()->GetName() :
"custom"));
2068 TVirtualStreamerInfo *TBufferJSON::GetInfo()
2070 return Stack()->fInfo;
2078 void TBufferJSON::SetStreamerElementNumber(TStreamerElement *elem, Int_t comp_type)
2081 Info(
"SetStreamerElementNumber",
"Element name %s", elem->GetName());
2083 WorkWithElement(elem, comp_type);
2091 void TBufferJSON::WorkWithElement(TStreamerElement *elem, Int_t)
2093 TJSONStackObj *stack = Stack();
2095 Error(
"WorkWithElement",
"stack is empty");
2100 Info(
"WorkWithElement",
" Start element %s type %d typename %s", elem ? elem->GetName() :
"---",
2101 elem ? elem->GetType() : -1, elem ? elem->GetTypeName() :
"---");
2103 if (stack->IsStreamerElement()) {
2108 Info(
"WorkWithElement",
" Perform post-processing elem: %s", stack->fElem->GetName());
2109 PerformPostProcessing(stack);
2118 Error(
"WorkWithElement",
"Lost of stack");
2122 TStreamerInfo *info = stack->fInfo;
2123 if (!stack->IsStreamerInfo()) {
2124 Error(
"WorkWithElement",
"Problem in Inc/Dec level");
2128 Int_t number = info ? info->GetElements()->IndexOf(elem) : -1;
2131 Error(
"WorkWithElement",
"streamer info returns elem = nullptr");
2135 TClass *base_class = elem->IsBase() ? elem->GetClassPointer() :
nullptr;
2137 stack = PushStack(0, stack->fNode);
2138 stack->fElem = elem;
2139 stack->fIsElemOwner = (number < 0);
2141 JsonStartElement(elem, base_class);
2143 if (base_class && IsReading())
2144 stack->fClVersion = base_class->GetClassVersion();
2146 if ((elem->GetType() == TStreamerInfo::kOffsetL + TStreamerInfo::kStreamLoop) && (elem->GetArrayDim() > 0)) {
2148 stack->fIndx = std::make_unique<TArrayIndexProducer>(elem, -1, fArraySepar.Data());
2150 AppendOutput(stack->fIndx->GetBegin());
2153 if (IsReading() && (elem->GetType() > TStreamerInfo::kOffsetP) && (elem->GetType() < TStreamerInfo::kOffsetP + 20)) {
2156 stack->PushIntValue(stack->IsJsonString() || (stack->IsJsonArray() > 0) ? 1 : 0);
2170 void TBufferJSON::ClassBegin(
const TClass *cl, Version_t)
2172 WorkWithClass(
nullptr, cl);
2179 void TBufferJSON::ClassEnd(
const TClass *)
2221 void TBufferJSON::ClassMember(
const char *name,
const char *typeName, Int_t arrsize1, Int_t arrsize2)
2226 if (!name || (strlen(name) == 0)) {
2227 Error(
"ClassMember",
"Invalid member name");
2231 TString tname = typeName;
2235 if (strcmp(typeName,
"raw:data") == 0)
2236 typ_id = TStreamerInfo::kMissing;
2239 TDataType *dt = gROOT->GetType(typeName);
2240 if (dt && (dt->GetType() > 0) && (dt->GetType() < 20))
2241 typ_id = dt->GetType();
2245 if (strcmp(name, typeName) == 0) {
2246 TClass *cl = TClass::GetClass(tname.Data());
2248 typ_id = TStreamerInfo::kBase;
2252 Bool_t isptr = kFALSE;
2253 if (tname[tname.Length() - 1] ==
'*') {
2254 tname.Resize(tname.Length() - 1);
2257 TClass *cl = TClass::GetClass(tname.Data());
2259 Error(
"ClassMember",
"Invalid class specifier %s", typeName);
2263 if (cl->IsTObject())
2264 typ_id = isptr ? TStreamerInfo::kObjectp : TStreamerInfo::kObject;
2266 typ_id = isptr ? TStreamerInfo::kAnyp : TStreamerInfo::kAny;
2268 if ((cl == TString::Class()) && !isptr)
2269 typ_id = TStreamerInfo::kTString;
2272 TStreamerElement *elem =
nullptr;
2274 if (typ_id == TStreamerInfo::kMissing) {
2275 elem =
new TStreamerElement(name,
"title", 0, typ_id,
"raw:data");
2276 }
else if (typ_id == TStreamerInfo::kBase) {
2277 TClass *cl = TClass::GetClass(tname.Data());
2279 TStreamerBase *b =
new TStreamerBase(tname.Data(),
"title", 0);
2280 b->SetBaseVersion(cl->GetClassVersion());
2283 }
else if ((typ_id > 0) && (typ_id < 20)) {
2284 elem =
new TStreamerBasicType(name,
"title", 0, typ_id, typeName);
2285 }
else if ((typ_id == TStreamerInfo::kObject) || (typ_id == TStreamerInfo::kTObject) ||
2286 (typ_id == TStreamerInfo::kTNamed)) {
2287 elem =
new TStreamerObject(name,
"title", 0, tname.Data());
2288 }
else if (typ_id == TStreamerInfo::kObjectp) {
2289 elem =
new TStreamerObjectPointer(name,
"title", 0, tname.Data());
2290 }
else if (typ_id == TStreamerInfo::kAny) {
2291 elem =
new TStreamerObjectAny(name,
"title", 0, tname.Data());
2292 }
else if (typ_id == TStreamerInfo::kAnyp) {
2293 elem =
new TStreamerObjectAnyPointer(name,
"title", 0, tname.Data());
2294 }
else if (typ_id == TStreamerInfo::kTString) {
2295 elem =
new TStreamerString(name,
"title", 0);
2299 Error(
"ClassMember",
"Invalid combination name = %s type = %s", name, typeName);
2304 elem->SetArrayDim(arrsize2 > 0 ? 2 : 1);
2305 elem->SetMaxIndex(0, arrsize1);
2307 elem->SetMaxIndex(1, arrsize2);
2311 WorkWithElement(elem, -1);
2317 void TBufferJSON::PerformPostProcessing(TJSONStackObj *stack,
const TClass *obj_cl)
2319 if (stack->fIsPostProcessed)
2322 const TStreamerElement *elem = stack->fElem;
2324 if (!elem && !obj_cl)
2327 stack->fIsPostProcessed = kTRUE;
2330 if (stack->fIsObjStarted) {
2331 AppendOutput(
"",
"}");
2335 Bool_t isTObject(kFALSE), isTRef(kFALSE), isTString(kFALSE), isSTLstring(kFALSE), isOffsetPArray(kFALSE),
2339 if (obj_cl == TObject::Class())
2341 else if (obj_cl == TRef::Class())
2346 const char *typname = elem->IsBase() ? elem->GetName() : elem->GetTypeName();
2347 isTObject = (elem->GetType() == TStreamerInfo::kTObject) || (strcmp(
"TObject", typname) == 0);
2348 isTString = elem->GetType() == TStreamerInfo::kTString;
2349 isSTLstring = elem->GetType() == TStreamerInfo::kSTLstring;
2350 isOffsetPArray = (elem->GetType() > TStreamerInfo::kOffsetP) && (elem->GetType() < TStreamerInfo::kOffsetP + 20);
2351 isTArray = (strncmp(
"TArray", typname, 6) == 0);
2354 if (isTString || isSTLstring) {
2358 Info(
"PerformPostProcessing",
"reformat string value = '%s'", fValue.Data());
2360 stack->fValues.clear();
2361 }
else if (isOffsetPArray) {
2364 if (stack->fValues.empty() && (fValue ==
"0")) {
2366 }
else if ((stack->fValues.size() == 1) && (stack->fValues[0] ==
"1")) {
2367 stack->fValues.clear();
2369 Error(
"PerformPostProcessing",
"Wrong values for kOffsetP element %s", (elem ? elem->GetName() :
"---"));
2370 stack->fValues.clear();
2373 }
else if (isTObject || isTRef) {
2378 Int_t cnt = stack->fValues.size();
2379 if (fValue.Length() > 0)
2382 if (cnt < 2 || cnt > 3) {
2384 Error(
"PerformPostProcessing",
"When storing TObject/TRef, strange number of items %d", cnt);
2385 AppendOutput(stack->NextMemberSeparator(),
"\"dummy\"");
2386 AppendOutput(fSemicolon.Data());
2388 AppendOutput(stack->NextMemberSeparator(),
"\"fUniqueID\"");
2389 AppendOutput(fSemicolon.Data());
2390 AppendOutput(stack->fValues[0].c_str());
2391 AppendOutput(stack->NextMemberSeparator(),
"\"fBits\"");
2392 AppendOutput(fSemicolon.Data());
2393 auto tbits = std::atol((stack->fValues.size() > 1) ? stack->fValues[1].c_str() : fValue.Data());
2394 AppendOutput(std::to_string(tbits & ~TObject::kNotDeleted & ~TObject::kIsOnHeap).c_str());
2396 AppendOutput(stack->NextMemberSeparator(),
"\"fPID\"");
2397 AppendOutput(fSemicolon.Data());
2398 AppendOutput((stack->fValues.size() > 2) ? stack->fValues[2].c_str() : fValue.Data());
2401 stack->fValues.clear();
2406 }
else if (isTArray) {
2408 stack->fValues.clear();
2411 if (elem && elem->IsBase() && (fValue.Length() == 0)) {
2416 if (!stack->fValues.empty()) {
2419 for (
auto &blob: stack->fValues) {
2420 AppendOutput(blob.c_str());
2421 AppendOutput(fArraySepar.Data());
2425 if (fValue.Length() == 0) {
2426 AppendOutput(
"null");
2428 AppendOutput(fValue.Data());
2432 if (!stack->fValues.empty())
2439 TClass *TBufferJSON::ReadClass(
const TClass *, UInt_t *)
2447 void TBufferJSON::WriteClass(
const TClass *) {}
2452 Version_t TBufferJSON::ReadVersion(UInt_t *start, UInt_t *bcnt,
const TClass *cl)
2454 Version_t res = cl ? cl->GetClassVersion() : 0;
2461 if (!cl && Stack()->fClVersion) {
2462 res = Stack()->fClVersion;
2463 Stack()->fClVersion = 0;
2467 Info(
"ReadVersion",
"Result: %d Class: %s", res, (cl ? cl->GetName() :
"---"));
2475 UInt_t TBufferJSON::WriteVersion(
const TClass * , Bool_t )
2483 void *TBufferJSON::ReadObjectAny(
const TClass *expectedClass)
2486 Info(
"ReadObjectAny",
"From current JSON node");
2487 void *res = JsonReadObject(
nullptr, expectedClass);
2494 void TBufferJSON::SkipObjectAny() {}
2499 void TBufferJSON::WriteObjectClass(
const void *actualObjStart,
const TClass *actualClass, Bool_t cacheReuse)
2502 Info(
"WriteObjectClass",
"Class %s", (actualClass ? actualClass->GetName() :
" null"));
2504 JsonWriteObject(actualObjStart, actualClass, cacheReuse);
2510 void TBufferJSON::JsonPushValue()
2512 if (fValue.Length() > 0)
2513 Stack()->PushValue(fValue);
2519 Int_t TBufferJSON::ReadArray(Bool_t *&b)
2521 return JsonReadArray(b);
2527 Int_t TBufferJSON::ReadArray(Char_t *&c)
2529 return JsonReadArray(c);
2535 Int_t TBufferJSON::ReadArray(UChar_t *&c)
2537 return JsonReadArray(c);
2543 Int_t TBufferJSON::ReadArray(Short_t *&h)
2545 return JsonReadArray(h);
2551 Int_t TBufferJSON::ReadArray(UShort_t *&h)
2553 return JsonReadArray(h);
2559 Int_t TBufferJSON::ReadArray(Int_t *&i)
2561 return JsonReadArray(i);
2567 Int_t TBufferJSON::ReadArray(UInt_t *&i)
2569 return JsonReadArray(i);
2575 Int_t TBufferJSON::ReadArray(Long_t *&l)
2577 return JsonReadArray(l);
2583 Int_t TBufferJSON::ReadArray(ULong_t *&l)
2585 return JsonReadArray(l);
2591 Int_t TBufferJSON::ReadArray(Long64_t *&l)
2593 return JsonReadArray(l);
2599 Int_t TBufferJSON::ReadArray(ULong64_t *&l)
2601 return JsonReadArray(l);
2607 Int_t TBufferJSON::ReadArray(Float_t *&f)
2609 return JsonReadArray(f);
2615 Int_t TBufferJSON::ReadArray(Double_t *&d)
2617 return JsonReadArray(d);
2623 template <
typename T>
2624 R__ALWAYS_INLINE Int_t TBufferJSON::JsonReadArray(T *value)
2626 Info(
"ReadArray",
"Not implemented");
2627 return value ? 1 : 0;
2633 Int_t TBufferJSON::ReadStaticArray(Bool_t *b)
2635 return JsonReadArray(b);
2641 Int_t TBufferJSON::ReadStaticArray(Char_t *c)
2643 return JsonReadArray(c);
2649 Int_t TBufferJSON::ReadStaticArray(UChar_t *c)
2651 return JsonReadArray(c);
2657 Int_t TBufferJSON::ReadStaticArray(Short_t *h)
2659 return JsonReadArray(h);
2665 Int_t TBufferJSON::ReadStaticArray(UShort_t *h)
2667 return JsonReadArray(h);
2673 Int_t TBufferJSON::ReadStaticArray(Int_t *i)
2675 return JsonReadArray(i);
2681 Int_t TBufferJSON::ReadStaticArray(UInt_t *i)
2683 return JsonReadArray(i);
2689 Int_t TBufferJSON::ReadStaticArray(Long_t *l)
2691 return JsonReadArray(l);
2697 Int_t TBufferJSON::ReadStaticArray(ULong_t *l)
2699 return JsonReadArray(l);
2705 Int_t TBufferJSON::ReadStaticArray(Long64_t *l)
2707 return JsonReadArray(l);
2713 Int_t TBufferJSON::ReadStaticArray(ULong64_t *l)
2715 return JsonReadArray(l);
2721 Int_t TBufferJSON::ReadStaticArray(Float_t *f)
2723 return JsonReadArray(f);
2729 Int_t TBufferJSON::ReadStaticArray(Double_t *d)
2731 return JsonReadArray(d);
2737 template <
typename T>
2738 R__ALWAYS_INLINE
void TBufferJSON::JsonReadFastArray(T *arr, Int_t arrsize,
bool asstring)
2740 if (!arr || (arrsize <= 0))
2742 nlohmann::json *json = Stack()->fNode;
2744 Info(
"ReadFastArray",
"Reading array sz %d from JSON %s", arrsize, json->dump().substr(0, 30).c_str());
2745 auto indexes = Stack()->MakeReadIndexes();
2747 TArrayI &indx = indexes->GetIndices();
2748 Int_t lastdim = indx.GetSize() - 1;
2749 if (indexes->TotalLength() != arrsize)
2750 Error(
"ReadFastArray",
"Mismatch %d-dim array sizes %d %d", lastdim + 1, arrsize, (
int)indexes->TotalLength());
2751 for (
int cnt = 0; cnt < arrsize; ++cnt) {
2752 nlohmann::json *elem = &(json->at(indx[0]));
2753 for (
int k = 1; k < lastdim; ++k)
2754 elem = &((*elem)[indx[k]]);
2755 arr[cnt] = asstring ? elem->get<std::string>()[indx[lastdim]] : (*elem)[indx[lastdim]].get<T>();
2756 indexes->NextSeparator();
2758 }
else if (asstring) {
2759 std::string str = json->get<std::string>();
2760 for (
int cnt = 0; cnt < arrsize; ++cnt)
2761 arr[cnt] = (cnt < (
int)str.length()) ? str[cnt] : 0;
2762 }
else if (json->is_object() && (json->count(
"$arr") == 1)) {
2763 if (json->at(
"len").get<
int>() != arrsize)
2764 Error(
"ReadFastArray",
"Mismatch compressed array size %d %d", arrsize, json->at(
"len").get<
int>());
2766 for (
int cnt = 0; cnt < arrsize; ++cnt)
2769 if (json->count(
"b") == 1) {
2770 auto base64 = json->at(
"b").get<std::string>();
2772 int offset = (json->count(
"o") == 1) ? json->at(
"o").get<
int>() : 0;
2775 auto decode = TBase64::Decode(base64.c_str());
2777 if (arrsize * (
long)
sizeof(T) < (offset + decode.Length())) {
2778 Error(
"ReadFastArray",
"Base64 data %ld larger than target array size %ld", (
long) decode.Length() + offset, (long) (arrsize*
sizeof(T)));
2779 }
else if ((
sizeof(T) > 1) && (decode.Length() %
sizeof(T) != 0)) {
2780 Error(
"ReadFastArray",
"Base64 data size %ld not matches with element size %ld", (
long) decode.Length(), (long)
sizeof(T));
2782 memcpy((
char *) arr + offset, decode.Data(), decode.Length());
2788 std::string idname =
"", pname, vname, nname;
2789 while (p < arrsize) {
2790 pname = std::string(
"p") + idname;
2791 if (json->count(pname) == 1)
2792 p = json->at(pname).get<
int>();
2793 vname = std::string(
"v") + idname;
2794 if (json->count(vname) != 1)
2796 nlohmann::json &v = json->at(vname);
2798 for (
unsigned sub = 0; sub < v.size(); ++sub)
2799 arr[p++] = v[sub].get<T>();
2801 nname = std::string(
"n") + idname;
2802 unsigned ncopy = (json->count(nname) == 1) ? json->at(nname).get<
unsigned>() : 1;
2803 for (
unsigned sub = 0; sub < ncopy; ++sub)
2804 arr[p++] = v.get<T>();
2806 idname = std::to_string(++
id);
2809 if ((
int)json->size() != arrsize)
2810 Error(
"ReadFastArray",
"Mismatch array sizes %d %d", arrsize, (
int)json->size());
2811 for (
int cnt = 0; cnt < arrsize; ++cnt)
2812 arr[cnt] = json->at(cnt).get<T>();
2819 void TBufferJSON::ReadFastArray(Bool_t *b, Int_t n)
2821 JsonReadFastArray(b, n);
2827 void TBufferJSON::ReadFastArray(Char_t *c, Int_t n)
2829 JsonReadFastArray(c, n,
true);
2835 void TBufferJSON::ReadFastArrayString(Char_t *c, Int_t n)
2837 JsonReadFastArray(c, n,
true);
2843 void TBufferJSON::ReadFastArray(UChar_t *c, Int_t n)
2845 JsonReadFastArray(c, n);
2851 void TBufferJSON::ReadFastArray(Short_t *h, Int_t n)
2853 JsonReadFastArray(h, n);
2859 void TBufferJSON::ReadFastArray(UShort_t *h, Int_t n)
2861 JsonReadFastArray(h, n);
2867 void TBufferJSON::ReadFastArray(Int_t *i, Int_t n)
2869 JsonReadFastArray(i, n);
2875 void TBufferJSON::ReadFastArray(UInt_t *i, Int_t n)
2877 JsonReadFastArray(i, n);
2883 void TBufferJSON::ReadFastArray(Long_t *l, Int_t n)
2885 JsonReadFastArray(l, n);
2891 void TBufferJSON::ReadFastArray(ULong_t *l, Int_t n)
2893 JsonReadFastArray(l, n);
2899 void TBufferJSON::ReadFastArray(Long64_t *l, Int_t n)
2901 JsonReadFastArray(l, n);
2907 void TBufferJSON::ReadFastArray(ULong64_t *l, Int_t n)
2909 JsonReadFastArray(l, n);
2915 void TBufferJSON::ReadFastArray(Float_t *f, Int_t n)
2917 JsonReadFastArray(f, n);
2923 void TBufferJSON::ReadFastArray(Double_t *d, Int_t n)
2925 JsonReadFastArray(d, n);
2934 void TBufferJSON::ReadFastArray(
void *start,
const TClass *cl, Int_t n, TMemberStreamer * ,
2938 Info(
"ReadFastArray",
"void* n:%d cl:%s", n, cl->GetName());
2947 int objectSize = cl->Size();
2948 char *obj = (
char *)start;
2950 TJSONStackObj *stack = Stack();
2951 nlohmann::json *topnode = stack->fNode, *subnode = topnode;
2953 subnode = stack->fIndx->ExtractNode(topnode);
2955 TArrayIndexProducer indexes(stack->fElem, n,
"");
2958 Info(
"ReadFastArray",
"Indexes ndim:%d totallen:%d", indexes.NumDimensions(), indexes.TotalLength());
2960 for (Int_t j = 0; j < n; j++, obj += objectSize) {
2962 stack->fNode = indexes.ExtractNode(subnode);
2964 JsonReadObject(obj, cl);
2968 stack->fNode = topnode;
2974 void TBufferJSON::ReadFastArray(
void **start,
const TClass *cl, Int_t n, Bool_t isPreAlloc,
2975 TMemberStreamer * ,
const TClass * )
2978 Info(
"ReadFastArray",
"void** n:%d cl:%s prealloc:%s", n, cl->GetName(), (isPreAlloc ?
"true" :
"false"));
2993 TJSONStackObj *stack = Stack();
2994 nlohmann::json *topnode = stack->fNode, *subnode = topnode;
2996 subnode = stack->fIndx->ExtractNode(topnode);
2998 TArrayIndexProducer indexes(stack->fElem, n,
"");
3000 for (Int_t j = 0; j < n; j++) {
3002 stack->fNode = indexes.ExtractNode(subnode);
3005 void *old = start[j];
3006 start[j] = JsonReadObject(
nullptr, cl);
3007 if (old && old != start[j] && TStreamerInfo::CanDelete())
3008 (
const_cast<TClass *
>(cl))->Destructor(old, kFALSE);
3011 start[j] = (
const_cast<TClass *
>(cl))->New();
3012 JsonReadObject(start[j], cl);
3016 stack->fNode = topnode;
3019 template <
typename T>
3020 R__ALWAYS_INLINE
void TBufferJSON::JsonWriteArrayCompress(
const T *vname, Int_t arrsize,
const char *typname)
3022 bool is_base64 = Stack()->fBase64 || (fArrayCompact == kBase64);
3024 if (!is_base64 && ((fArrayCompact == 0) || (arrsize < 6))) {
3026 for (Int_t indx = 0; indx < arrsize; indx++) {
3028 fValue.Append(fArraySepar.Data());
3029 JsonWriteBasic(vname[indx]);
3032 }
else if (is_base64 && !arrsize) {
3033 fValue.Append(
"[]");
3036 fValue.Append(TString::Format(
"\"$arr\":\"%s\"%s\"len\":%d", typname, fArraySepar.Data(), arrsize));
3037 Int_t aindx(0), bindx(arrsize);
3038 while ((aindx < arrsize) && (vname[aindx] == 0))
3040 while ((aindx < bindx) && (vname[bindx - 1] == 0))
3045 if ((aindx *
sizeof(T) < 5) && (aindx < bindx))
3048 if ((aindx > 0) && (aindx < bindx))
3049 fValue.Append(TString::Format(
"%s\"o\":%ld", fArraySepar.Data(), (long) (aindx * (
int)
sizeof(T))));
3051 fValue.Append(fArraySepar);
3052 fValue.Append(
"\"b\":\"");
3055 fValue.Append(TBase64::Encode((
const char *) (vname + aindx), (bindx - aindx) *
sizeof(T)));
3057 fValue.Append(
"\"");
3058 }
else if (aindx < bindx) {
3060 Int_t p(aindx), suffixcnt(-1), lastp(0);
3062 if (vname[p] == 0) {
3066 Int_t p0(p++), pp(0), nsame(1);
3067 if (fArrayCompact != kSameSuppression) {
3072 for (; p <= bindx; ++p) {
3073 if ((p < bindx) && (vname[p] == vname[p - 1])) {
3077 if (vname[p - 1] == 0) {
3082 }
else if (nsame > 5) {
3095 if (++suffixcnt > 0)
3096 suffix.Form(
"%d", suffixcnt);
3098 fValue.Append(TString::Format(
"%s\"p%s\":%d", fArraySepar.Data(), suffix.Data(), p0));
3100 fValue.Append(TString::Format(
"%s\"v%s\":", fArraySepar.Data(), suffix.Data()));
3101 if ((nsame > 1) || (pp - p0 == 1)) {
3102 JsonWriteBasic(vname[p0]);
3104 fValue.Append(TString::Format(
"%s\"n%s\":%d", fArraySepar.Data(), suffix.Data(), nsame));
3107 for (Int_t indx = p0; indx < pp; indx++) {
3109 fValue.Append(fArraySepar.Data());
3110 JsonWriteBasic(vname[indx]);
3123 void TBufferJSON::WriteArray(
const Bool_t *b, Int_t n)
3126 JsonWriteArrayCompress(b, n,
"Bool");
3132 void TBufferJSON::WriteArray(
const Char_t *c, Int_t n)
3135 JsonWriteArrayCompress(c, n,
"Int8");
3141 void TBufferJSON::WriteArray(
const UChar_t *c, Int_t n)
3144 JsonWriteArrayCompress(c, n,
"Uint8");
3150 void TBufferJSON::WriteArray(
const Short_t *h, Int_t n)
3153 JsonWriteArrayCompress(h, n,
"Int16");
3159 void TBufferJSON::WriteArray(
const UShort_t *h, Int_t n)
3162 JsonWriteArrayCompress(h, n,
"Uint16");
3168 void TBufferJSON::WriteArray(
const Int_t *i, Int_t n)
3171 JsonWriteArrayCompress(i, n,
"Int32");
3177 void TBufferJSON::WriteArray(
const UInt_t *i, Int_t n)
3180 JsonWriteArrayCompress(i, n,
"Uint32");
3186 void TBufferJSON::WriteArray(
const Long_t *l, Int_t n)
3189 JsonWriteArrayCompress(l, n,
"Int64");
3195 void TBufferJSON::WriteArray(
const ULong_t *l, Int_t n)
3198 JsonWriteArrayCompress(l, n,
"Uint64");
3204 void TBufferJSON::WriteArray(
const Long64_t *l, Int_t n)
3207 JsonWriteArrayCompress(l, n,
"Int64");
3213 void TBufferJSON::WriteArray(
const ULong64_t *l, Int_t n)
3216 JsonWriteArrayCompress(l, n,
"Uint64");
3222 void TBufferJSON::WriteArray(
const Float_t *f, Int_t n)
3225 JsonWriteArrayCompress(f, n,
"Float32");
3231 void TBufferJSON::WriteArray(
const Double_t *d, Int_t n)
3234 JsonWriteArrayCompress(d, n,
"Float64");
3242 template <
typename T>
3243 R__ALWAYS_INLINE
void TBufferJSON::JsonWriteFastArray(
const T *arr, Int_t arrsize,
const char *typname,
3244 void (TBufferJSON::*method)(
const T *, Int_t,
const char *))
3248 fValue.Append(
"[]");
3252 TStreamerElement *elem = Stack()->fElem;
3253 if (elem && (elem->GetArrayDim() > 1) && (elem->GetArrayLength() == arrsize)) {
3254 TArrayI indexes(elem->GetArrayDim() - 1);
3256 Int_t cnt = 0, shift = 0, len = elem->GetMaxIndex(indexes.GetSize());
3258 if (indexes[cnt] >= elem->GetMaxIndex(cnt)) {
3265 fValue.Append(indexes[cnt] == 0 ?
"[" : fArraySepar.Data());
3266 if (++cnt == indexes.GetSize()) {
3267 (*this.*method)((arr + shift), len, typname);
3273 (*this.*method)(arr, arrsize, typname);
3280 void TBufferJSON::WriteFastArray(
const Bool_t *b, Int_t n)
3282 JsonWriteFastArray(b, n,
"Bool", &TBufferJSON::JsonWriteArrayCompress<Bool_t>);
3288 void TBufferJSON::WriteFastArray(
const Char_t *c, Int_t n)
3290 JsonWriteFastArray(c, n,
"Int8", &TBufferJSON::JsonWriteConstChar);
3296 void TBufferJSON::WriteFastArrayString(
const Char_t *c, Int_t n)
3298 JsonWriteFastArray(c, n,
"Int8", &TBufferJSON::JsonWriteConstChar);
3304 void TBufferJSON::WriteFastArray(
const UChar_t *c, Int_t n)
3306 JsonWriteFastArray(c, n,
"Uint8", &TBufferJSON::JsonWriteArrayCompress<UChar_t>);
3312 void TBufferJSON::WriteFastArray(
const Short_t *h, Int_t n)
3314 JsonWriteFastArray(h, n,
"Int16", &TBufferJSON::JsonWriteArrayCompress<Short_t>);
3320 void TBufferJSON::WriteFastArray(
const UShort_t *h, Int_t n)
3322 JsonWriteFastArray(h, n,
"Uint16", &TBufferJSON::JsonWriteArrayCompress<UShort_t>);
3328 void TBufferJSON::WriteFastArray(
const Int_t *i, Int_t n)
3330 JsonWriteFastArray(i, n,
"Int32", &TBufferJSON::JsonWriteArrayCompress<Int_t>);
3336 void TBufferJSON::WriteFastArray(
const UInt_t *i, Int_t n)
3338 JsonWriteFastArray(i, n,
"Uint32", &TBufferJSON::JsonWriteArrayCompress<UInt_t>);
3344 void TBufferJSON::WriteFastArray(
const Long_t *l, Int_t n)
3346 JsonWriteFastArray(l, n,
"Int64", &TBufferJSON::JsonWriteArrayCompress<Long_t>);
3352 void TBufferJSON::WriteFastArray(
const ULong_t *l, Int_t n)
3354 JsonWriteFastArray(l, n,
"Uint64", &TBufferJSON::JsonWriteArrayCompress<ULong_t>);
3360 void TBufferJSON::WriteFastArray(
const Long64_t *l, Int_t n)
3362 JsonWriteFastArray(l, n,
"Int64", &TBufferJSON::JsonWriteArrayCompress<Long64_t>);
3368 void TBufferJSON::WriteFastArray(
const ULong64_t *l, Int_t n)
3370 JsonWriteFastArray(l, n,
"Uint64", &TBufferJSON::JsonWriteArrayCompress<ULong64_t>);
3376 void TBufferJSON::WriteFastArray(
const Float_t *f, Int_t n)
3378 JsonWriteFastArray(f, n,
"Float32", &TBufferJSON::JsonWriteArrayCompress<Float_t>);
3384 void TBufferJSON::WriteFastArray(
const Double_t *d, Int_t n)
3386 JsonWriteFastArray(d, n,
"Float64", &TBufferJSON::JsonWriteArrayCompress<Double_t>);
3392 void TBufferJSON::WriteFastArray(
void *start,
const TClass *cl, Int_t n, TMemberStreamer * )
3395 Info(
"WriteFastArray",
"void *start cl:%s n:%d", cl ? cl->GetName() :
"---", n);
3405 AppendOutput(
"null");
3406 JsonDisablePostprocessing();
3409 char *obj = (
char *)start;
3412 int size = cl->Size();
3414 TArrayIndexProducer indexes(Stack()->fElem, n, fArraySepar.Data());
3416 if (indexes.IsArray()) {
3417 JsonDisablePostprocessing();
3418 AppendOutput(indexes.GetBegin());
3421 for (Int_t j = 0; j < n; j++, obj += size) {
3424 AppendOutput(indexes.NextSeparator());
3426 JsonWriteObject(obj, cl, kFALSE);
3428 if (indexes.IsArray() && (fValue.Length() > 0)) {
3429 AppendOutput(fValue.Data());
3434 if (indexes.IsArray())
3435 AppendOutput(indexes.GetEnd());
3439 AppendOutput(Stack()->fIndx->NextSeparator());
3445 Int_t TBufferJSON::WriteFastArray(
void **start,
const TClass *cl, Int_t n, Bool_t isPreAlloc,
3449 Info(
"WriteFastArray",
"void **startp cl:%s n:%d", cl->GetName(), n);
3462 TArrayIndexProducer indexes(Stack()->fElem, n, fArraySepar.Data());
3464 if (indexes.IsArray()) {
3465 JsonDisablePostprocessing();
3466 AppendOutput(indexes.GetBegin());
3469 for (Int_t j = 0; j < n; j++) {
3472 AppendOutput(indexes.NextSeparator());
3475 res |= WriteObjectAny(start[j], cl);
3478 start[j] = (
const_cast<TClass *
>(cl))->New();
3480 JsonWriteObject(start[j], cl, kFALSE);
3483 if (indexes.IsArray() && (fValue.Length() > 0)) {
3484 AppendOutput(fValue.Data());
3489 if (indexes.IsArray())
3490 AppendOutput(indexes.GetEnd());
3493 AppendOutput(Stack()->fIndx->NextSeparator());
3501 void TBufferJSON::StreamObject(
void *obj,
const TClass *cl,
const TClass * )
3504 Info(
"StreamObject",
"Class: %s", (cl ? cl->GetName() :
"none"));
3507 JsonWriteObject(obj, cl);
3509 JsonReadObject(obj, cl);
3515 template <
typename T>
3516 R__ALWAYS_INLINE
void TBufferJSON::JsonReadBasic(T &value)
3518 value = Stack()->GetStlNode()->get<T>();
3524 void TBufferJSON::ReadBool(Bool_t &val)
3532 void TBufferJSON::ReadChar(Char_t &val)
3534 if (!Stack()->fValues.empty())
3535 val = (Char_t)Stack()->PopIntValue();
3537 val = Stack()->GetStlNode()->get<Char_t>();
3543 void TBufferJSON::ReadUChar(UChar_t &val)
3551 void TBufferJSON::ReadShort(Short_t &val)
3559 void TBufferJSON::ReadUShort(UShort_t &val)
3567 void TBufferJSON::ReadInt(Int_t &val)
3569 if (!Stack()->fValues.empty())
3570 val = Stack()->PopIntValue();
3578 void TBufferJSON::ReadUInt(UInt_t &val)
3586 void TBufferJSON::ReadLong(Long_t &val)
3594 void TBufferJSON::ReadULong(ULong_t &val)
3602 void TBufferJSON::ReadLong64(Long64_t &val)
3610 void TBufferJSON::ReadULong64(ULong64_t &val)
3618 void TBufferJSON::ReadFloat(Float_t &val)
3620 nlohmann::json *json = Stack()->GetStlNode();
3621 if (json->is_null())
3622 val = std::numeric_limits<Float_t>::quiet_NaN();
3624 val = json->get<Float_t>();
3630 void TBufferJSON::ReadDouble(Double_t &val)
3632 nlohmann::json *json = Stack()->GetStlNode();
3633 if (json->is_null())
3634 val = std::numeric_limits<Double_t>::quiet_NaN();
3636 val = json->get<Double_t>();
3642 void TBufferJSON::ReadCharP(Char_t *)
3644 Error(
"ReadCharP",
"Not implemented");
3650 void TBufferJSON::ReadTString(TString &val)
3660 void TBufferJSON::ReadStdString(std::string *val)
3662 JsonReadBasic(*val);
3668 void TBufferJSON::ReadCharStar(
char *&s)
3678 std::size_t nch = str.length();
3680 s =
new char[nch + 1];
3681 memcpy(s, str.c_str(), nch);
3689 void TBufferJSON::WriteBool(Bool_t b)
3698 void TBufferJSON::WriteChar(Char_t c)
3707 void TBufferJSON::WriteUChar(UChar_t c)
3716 void TBufferJSON::WriteShort(Short_t h)
3725 void TBufferJSON::WriteUShort(UShort_t h)
3734 void TBufferJSON::WriteInt(Int_t i)
3743 void TBufferJSON::WriteUInt(UInt_t i)
3752 void TBufferJSON::WriteLong(Long_t l)
3761 void TBufferJSON::WriteULong(ULong_t l)
3770 void TBufferJSON::WriteLong64(Long64_t l)
3779 void TBufferJSON::WriteULong64(ULong64_t l)
3788 void TBufferJSON::WriteFloat(Float_t f)
3797 void TBufferJSON::WriteDouble(Double_t d)
3806 void TBufferJSON::WriteCharP(
const Char_t *c)
3810 JsonWriteConstChar(c);
3816 void TBufferJSON::WriteTString(
const TString &s)
3820 JsonWriteConstChar(s.Data(), s.Length());
3826 void TBufferJSON::WriteStdString(
const std::string *s)
3831 JsonWriteConstChar(s->c_str(), s->length());
3833 JsonWriteConstChar(
"", 0);
3839 void TBufferJSON::WriteCharStar(
char *s)
3843 JsonWriteConstChar(s);
3849 void TBufferJSON::JsonWriteBasic(Char_t value)
3852 snprintf(buf,
sizeof(buf),
"%d", value);
3859 void TBufferJSON::JsonWriteBasic(Short_t value)
3862 snprintf(buf,
sizeof(buf),
"%hd", value);
3869 void TBufferJSON::JsonWriteBasic(Int_t value)
3872 snprintf(buf,
sizeof(buf),
"%d", value);
3879 void TBufferJSON::JsonWriteBasic(Long_t value)
3882 snprintf(buf,
sizeof(buf),
"%ld", value);
3889 void TBufferJSON::JsonWriteBasic(Long64_t value)
3891 fValue.Append(std::to_string(value).c_str());
3897 void TBufferJSON::JsonWriteBasic(Float_t value)
3899 if (std::isinf(value)) {
3900 fValue.Append((value < 0.) ?
"-2e308" :
"2e308");
3901 }
else if (std::isnan(value)) {
3902 fValue.Append(
"null");
3905 ConvertFloat(value, buf,
sizeof(buf));
3913 void TBufferJSON::JsonWriteBasic(Double_t value)
3915 if (std::isinf(value)) {
3916 fValue.Append((value < 0.) ?
"-2e308" :
"2e308");
3917 }
else if (std::isnan(value)) {
3918 fValue.Append(
"null");
3921 ConvertDouble(value, buf,
sizeof(buf));
3929 void TBufferJSON::JsonWriteBasic(Bool_t value)
3931 fValue.Append(value ?
"true" :
"false");
3937 void TBufferJSON::JsonWriteBasic(UChar_t value)
3940 snprintf(buf,
sizeof(buf),
"%u", value);
3947 void TBufferJSON::JsonWriteBasic(UShort_t value)
3950 snprintf(buf,
sizeof(buf),
"%hu", value);
3957 void TBufferJSON::JsonWriteBasic(UInt_t value)
3960 snprintf(buf,
sizeof(buf),
"%u", value);
3967 void TBufferJSON::JsonWriteBasic(ULong_t value)
3970 snprintf(buf,
sizeof(buf),
"%lu", value);
3977 void TBufferJSON::JsonWriteBasic(ULong64_t value)
3979 fValue.Append(std::to_string(value).c_str());
3985 void TBufferJSON::JsonWriteConstChar(
const char *value, Int_t len,
const char * )
3989 fValue.Append(
"\"\"");
3993 fValue.Append(
"\"");
3996 len = strlen(value);
3998 for (Int_t n = 0; n < len; n++) {
4003 case '\n': fValue.Append(
"\\n");
break;
4004 case '\t': fValue.Append(
"\\t");
break;
4005 case '\"': fValue.Append(
"\\\"");
break;
4006 case '\\': fValue.Append(
"\\\\");
break;
4007 case '\b': fValue.Append(
"\\b");
break;
4008 case '\f': fValue.Append(
"\\f");
break;
4009 case '\r': fValue.Append(
"\\r");
break;
4010 case '/': fValue.Append(
"\\/");
break;
4012 if ((c > 31) && (c < 127))
4015 fValue.Append(TString::Format(
"\\u%04x", (
unsigned)c));
4019 fValue.Append(
"\"");
4026 void TBufferJSON::ReadBaseClass(
void *start, TStreamerBase *elem)
4028 if (elem->GetClassPointer() == TObject::Class()) {
4029 JsonReadTObjectMembers((TObject *)start);
4031 TBufferText::ReadBaseClass(start, elem);