#include "TBufferJSON.h"
#include <typeinfo>
#include "Compression.h"
#include "TArrayI.h"
#include "TObjArray.h"
#include "TROOT.h"
#include "TClass.h"
#include "TClassTable.h"
#include "TClassEdit.h"
#include "TDataType.h"
#include "TDataMember.h"
#include "TMath.h"
#include "TExMap.h"
#include "TMethodCall.h"
#include "TStreamerInfo.h"
#include "TStreamerElement.h"
#include "TProcessID.h"
#include "TFile.h"
#include "TMemberStreamer.h"
#include "TStreamer.h"
#include "TStreamerInfoActions.h"
#include "RVersion.h"
#include "TClonesArray.h"
#include "TVirtualMutex.h"
#include "TInterpreter.h"
#ifdef R__VISUAL_CPLUSPLUS
#define FLong64 "%I64d"
#define FULong64 "%I64u"
#else
#define FLong64 "%lld"
#define FULong64 "%llu"
#endif
ClassImp(TBufferJSON);
const char *TBufferJSON::fgFloatFmt = "%e";
class TJSONStackObj : public TObject {
public:
TStreamerInfo *fInfo;
TStreamerElement *fElem;
Int_t fElemNumber;
Bool_t fIsStreamerInfo;
Bool_t fIsElemOwner;
Bool_t fIsPostProcessed;
Bool_t fIsObjStarted;
Bool_t fAccObjects;
TObjArray fValues;
Int_t fLevel;
TJSONStackObj() :
TObject(),
fInfo(0),
fElem(0),
fElemNumber(0),
fIsStreamerInfo(kFALSE),
fIsElemOwner(kFALSE),
fIsPostProcessed(kFALSE),
fIsObjStarted(kFALSE),
fAccObjects(kFALSE),
fValues(),
fLevel(0)
{
fValues.SetOwner(kTRUE);
}
virtual ~TJSONStackObj()
{
if (fIsElemOwner) delete fElem;
}
Bool_t IsStreamerInfo() const
{
return fIsStreamerInfo;
}
Bool_t IsStreamerElement() const
{
return !fIsStreamerInfo && (fElem != 0);
}
void PushValue(TString &v)
{
fValues.Add(new TObjString(v));
v.Clear();
}
};
TBufferJSON::TBufferJSON() :
TBuffer(TBuffer::kWrite),
fOutBuffer(),
fOutput(0),
fValue(),
fJsonrMap(),
fJsonrCnt(0),
fStack(),
fExpectedChain(kFALSE),
fCompact(0),
fSemicolon(" : "),
fArraySepar(", ")
{
fBufSize = 1000000000;
SetParent(0);
SetBit(kCannotHandleMemberWiseStreaming);
fOutBuffer.Capacity(10000);
fValue.Capacity(1000);
fOutput = &fOutBuffer;
}
TBufferJSON::~TBufferJSON()
{
fStack.Delete();
}
TString TBufferJSON::ConvertToJSON(const TObject *obj, Int_t compact)
{
return ConvertToJSON(obj, (obj ? obj->IsA() : 0), compact);
}
void TBufferJSON::SetCompact(int level)
{
fCompact = level;
fSemicolon = fCompact > 2 ? ":" : " : ";
fArraySepar = fCompact > 2 ? "," : ", ";
}
TString TBufferJSON::ConvertToJSON(const void *obj, const TClass *cl,
Int_t compact)
{
TBufferJSON buf;
buf.SetCompact(compact);
buf.JsonWriteObject(obj, cl);
return buf.fOutBuffer.Length() ? buf.fOutBuffer : buf.fValue;
}
TString TBufferJSON::ConvertToJSON(const void *ptr, TDataMember *member,
Int_t compact)
{
if ((ptr == 0) || (member == 0)) return TString("null");
Bool_t stlstring = !strcmp(member->GetTrueTypeName(),"string");
Int_t isstl = member->IsSTLContainer();
TClass *mcl = member->IsBasic() ? 0 : gROOT->GetClass(member->GetTypeName());
if ((mcl != 0) && (mcl != TString::Class()) && !stlstring && !isstl &&
(mcl->GetBaseClassOffset(TArray::Class()) != 0))
return TBufferJSON::ConvertToJSON(ptr, mcl, compact);
TBufferJSON buf;
buf.SetCompact(compact);
return buf.JsonWriteMember(ptr, member, mcl);
}
TString TBufferJSON::JsonWriteMember(const void *ptr, TDataMember *member,
TClass *memberClass)
{
if (member == 0) return "null";
if (gDebug > 2)
Info("JsonWriteMember", "Write member %s type %s ndim %d",
member->GetName(), member->GetTrueTypeName(), member->GetArrayDim());
PushStack(0);
fValue.Clear();
if (member->IsBasic()) {
Int_t tid = member->GetDataType() ? member->GetDataType()->GetType() : kNoType_t;
if (ptr == 0) {
fValue = "null";
} else if (member->GetArrayDim() == 0) {
switch (tid) {
case kChar_t:
JsonWriteBasic(*((Char_t *)ptr));
break;
case kShort_t:
JsonWriteBasic(*((Short_t *)ptr));
break;
case kInt_t:
JsonWriteBasic(*((Int_t *)ptr));
break;
case kLong_t:
JsonWriteBasic(*((Long_t *)ptr));
break;
case kFloat_t:
JsonWriteBasic(*((Float_t *)ptr));
break;
case kCounter:
JsonWriteBasic(*((Int_t *)ptr));
break;
case kCharStar:
WriteCharP((Char_t *)ptr);
break;
case kDouble_t:
JsonWriteBasic(*((Double_t *)ptr));
break;
case kDouble32_t:
JsonWriteBasic(*((Double_t *)ptr));
break;
case kchar:
JsonWriteBasic(*((char *)ptr));
break;
case kUChar_t:
JsonWriteBasic(*((UChar_t *)ptr));
break;
case kUShort_t:
JsonWriteBasic(*((UShort_t *)ptr));
break;
case kUInt_t:
JsonWriteBasic(*((UInt_t *)ptr));
break;
case kULong_t:
JsonWriteBasic(*((ULong_t *)ptr));
break;
case kBits:
JsonWriteBasic(*((UInt_t *)ptr));
break;
case kLong64_t:
JsonWriteBasic(*((Long64_t *)ptr));
break;
case kULong64_t:
JsonWriteBasic(*((ULong64_t *)ptr));
break;
case kBool_t:
JsonWriteBasic(*((Bool_t *)ptr));
break;
case kFloat16_t:
JsonWriteBasic(*((Float_t *)ptr));
break;
case kOther_t:
case kNoType_t:
case kVoid_t:
break;
}
} else if ((member->GetArrayDim() == 1) || (fCompact > 0)) {
Int_t n = member->GetMaxIndex(0);
for (Int_t ndim = 1; ndim < member->GetArrayDim(); ndim++)
n *= member->GetMaxIndex(ndim);
switch (tid) {
case kChar_t:
WriteFastArray((Char_t *)ptr, n);
break;
case kShort_t:
WriteFastArray((Short_t *)ptr, n);
break;
case kInt_t:
WriteFastArray((Int_t *)ptr, n);
break;
case kLong_t:
WriteFastArray((Long_t *)ptr, n);
break;
case kFloat_t:
WriteFastArray((Float_t *)ptr, n);
break;
case kCounter:
WriteFastArray((Int_t *)ptr, n);
break;
case kCharStar:
WriteFastArray((Char_t *)ptr, n);
break;
case kDouble_t:
WriteFastArray((Double_t *)ptr, n);
break;
case kDouble32_t:
WriteFastArray((Double_t *)ptr, n);
break;
case kchar:
WriteFastArray((char *)ptr, n);
break;
case kUChar_t:
WriteFastArray((UChar_t *)ptr, n);
break;
case kUShort_t:
WriteFastArray((UShort_t *)ptr, n);
break;
case kUInt_t:
WriteFastArray((UInt_t *)ptr, n);
break;
case kULong_t:
WriteFastArray((ULong_t *)ptr, n);
break;
case kBits:
WriteFastArray((UInt_t *)ptr, n);
break;
case kLong64_t:
WriteFastArray((Long64_t *)ptr, n);
break;
case kULong64_t:
WriteFastArray((ULong64_t *)ptr, n);
break;
case kBool_t:
WriteFastArray((Bool_t *)ptr, n);
break;
case kFloat16_t:
WriteFastArray((Float_t *)ptr, n);
break;
case kOther_t:
case kNoType_t:
case kVoid_t:
break;
}
} else {
TArrayI indexes(member->GetArrayDim() - 1);
indexes.Reset(0);
Int_t cnt = 0;
while (cnt >= 0) {
if (indexes[cnt] >= member->GetMaxIndex(cnt)) {
fOutBuffer.Append(" ]");
indexes[cnt] = 0;
cnt--;
if (cnt >= 0) indexes[cnt]++;
continue;
}
if (indexes[cnt] > 0)
fOutBuffer.Append(fArraySepar);
else
fOutBuffer.Append("[ ");
if (++cnt == indexes.GetSize()) {
Int_t shift = 0;
for (Int_t k = 0; k < indexes.GetSize(); k++) {
shift = shift * member->GetMaxIndex(k) + indexes[k];
}
Int_t len = member->GetMaxIndex(indexes.GetSize());
shift *= len;
fValue.Clear();
WriteFastArray((Int_t *)ptr + shift, len);
switch (tid) {
case kChar_t:
WriteFastArray((Char_t *)ptr + shift, len);
break;
case kShort_t:
WriteFastArray((Short_t *)ptr + shift, len);
break;
case kInt_t:
WriteFastArray((Int_t *)ptr + shift, len);
break;
case kLong_t:
WriteFastArray((Long_t *)ptr + shift, len);
break;
case kFloat_t:
WriteFastArray((Float_t *)ptr + shift, len);
break;
case kCounter:
WriteFastArray((Int_t *)ptr + shift, len);
break;
case kCharStar:
WriteFastArray((Char_t *)ptr + shift, len);
break;
case kDouble_t:
WriteFastArray((Double_t *)ptr + shift, len);
break;
case kDouble32_t:
WriteFastArray((Double_t *)ptr + shift, len);
break;
case kchar:
WriteFastArray((char *)ptr + shift, len);
break;
case kUChar_t:
WriteFastArray((UChar_t *)ptr + shift, len);
break;
case kUShort_t:
WriteFastArray((UShort_t *)ptr + shift, len);
break;
case kUInt_t:
WriteFastArray((UInt_t *)ptr + shift, len);
break;
case kULong_t:
WriteFastArray((ULong_t *)ptr + shift, len);
break;
case kBits:
WriteFastArray((UInt_t *)ptr + shift, len);
break;
case kLong64_t:
WriteFastArray((Long64_t *)ptr + shift, len);
break;
case kULong64_t:
WriteFastArray((ULong64_t *)ptr + shift, len);
break;
case kBool_t:
WriteFastArray((Bool_t *)ptr + shift, len);
break;
case kFloat16_t:
WriteFastArray((Float_t *)ptr + shift, len);
break;
case kOther_t:
case kNoType_t:
case kVoid_t:
fValue = "null";
break;
}
fOutBuffer.Append(fValue);
cnt--;
indexes[cnt]++;
}
}
fValue = fOutBuffer;
}
} else if (memberClass == TString::Class()) {
TString *str = (TString *) ptr;
fValue.Append("\"");
if (str != 0) fValue.Append(*str);
fValue.Append("\"");
} else if ((member->IsSTLContainer()==ROOT::kSTLvector) || (member->IsSTLContainer()==ROOT::kSTLlist)) {
if (memberClass)
((TClass *)memberClass)->Streamer((void *)ptr, *this);
else
fValue = "[]";
if (fValue=="0") fValue = "[]";
} else if (memberClass && memberClass->GetBaseClassOffset(TArray::Class()) == 0) {
TArray *arr = (TArray *) ptr;
if ((arr != 0) && (arr->GetSize() > 0)) {
arr->Streamer(*this);
if (Stack()->fValues.GetLast() > 0) {
Warning("TBufferJSON", "When streaming TArray, more than 1 object in the stack, use second item");
fValue = Stack()->fValues.At(1)->GetName();
}
} else
fValue = "[]";
} else if (memberClass && !strcmp(memberClass->GetName(),"string")) {
((TClass *)memberClass)->Streamer((void *)ptr, *this);
}
PopStack();
if (fValue.Length()) return fValue;
if ((memberClass==0) || (member->GetArrayDim()>0)) return "\"not supported\"";
return TBufferJSON::ConvertToJSON(ptr, memberClass);
}
Bool_t TBufferJSON::CheckObject(const TObject * obj)
{
if (obj==0) return kTRUE;
return fJsonrMap.find(obj) != fJsonrMap.end();
}
Bool_t TBufferJSON::CheckObject(const void * ptr, const TClass * )
{
if (ptr==0) return kTRUE;
return fJsonrMap.find(ptr) != fJsonrMap.end();
}
void TBufferJSON::WriteObject(const TObject *obj)
{
if (gDebug>1)
Info("WriteObject", "Object %p", obj);
WriteObjectAny(obj, TObject::Class());
}
TJSONStackObj *TBufferJSON::PushStack(Int_t inclevel)
{
TJSONStackObj *curr = Stack();
TJSONStackObj *stack = new TJSONStackObj();
stack->fLevel = (curr ? curr->fLevel : 0) + inclevel;
fStack.Add(stack);
return stack;
}
TJSONStackObj *TBufferJSON::PopStack()
{
TObject *last = fStack.Last();
if (last != 0) {
fStack.Remove(last);
delete last;
fStack.Compress();
}
return dynamic_cast<TJSONStackObj *>(fStack.Last());
}
TJSONStackObj *TBufferJSON::Stack(Int_t depth)
{
TJSONStackObj *stack = 0;
if (depth <= fStack.GetLast())
stack = dynamic_cast<TJSONStackObj *>(fStack.At(fStack.GetLast() - depth));
return stack;
}
void TBufferJSON::AppendOutput(const char *line0, const char *line1)
{
if (line0 != 0) fOutput->Append(line0);
if (line1 != 0) {
if (fCompact < 2) fOutput->Append("\n");
if (strlen(line1) > 0) {
if (fCompact < 1) {
TJSONStackObj *stack = Stack();
if ((stack != 0) && (stack->fLevel > 0))
fOutput->Append(' ', stack->fLevel);
}
fOutput->Append(line1);
}
}
}
void TBufferJSON::JsonStartElement(const TStreamerElement *elem, const TClass* base_class)
{
const char* elem_name = 0;
if (base_class == 0) {
elem_name = elem->GetName();
} else {
switch(JsonSpecialClass(base_class)) {
case TClassEdit::kVector : elem_name = "fVector"; break;
case TClassEdit::kList : elem_name = "fList"; break;
case TClassEdit::kDeque : elem_name = "fDeque"; break;
case TClassEdit::kMap : elem_name = "fMap"; break;
case TClassEdit::kMultiMap : elem_name = "fMultiMap"; break;
case TClassEdit::kSet : elem_name = "fSet"; break;
case TClassEdit::kMultiSet : elem_name = "fMultiSet"; break;
case TClassEdit::kBitSet : elem_name = "fBitSet"; break;
case 100: elem_name = "fArray"; break;
case 110:
case 120: elem_name = "fString"; break;
}
}
if (elem_name!=0) {
AppendOutput(",", "\"");
AppendOutput(elem_name);
AppendOutput("\"");
AppendOutput(fSemicolon.Data());
}
}
void TBufferJSON::JsonDisablePostprocessing()
{
TJSONStackObj *stack = Stack();
if (stack!=0) stack->fIsPostProcessed = kTRUE;
}
Int_t TBufferJSON::JsonSpecialClass(const TClass* cl) const
{
if (cl==0) return 0;
Bool_t isarray = strncmp("TArray", cl->GetName(), 6) == 0;
if (isarray) isarray = ((TClass *)cl)->GetBaseClassOffset(TArray::Class()) == 0;
if (isarray) return 100;
if (((TClass *)cl)->GetBaseClassOffset(TCollection::Class()) == 0) return -130;
if (cl == TString::Class()) return 110;
bool isstd = TClassEdit::IsStdClass(cl->GetName());
int isstlcont(0);
if (isstd) isstlcont = TMath::Abs((Int_t)TClassEdit::IsSTLCont(cl->GetName()));
if (isstlcont>0) return isstlcont;
if (isstd && !strcmp(cl->GetName(),"string")) return 120;
return 0;
}
void TBufferJSON::JsonWriteObject(const void *obj, const TClass *cl, Bool_t check_map)
{
if (!cl) obj = 0;
if (gDebug > 0)
Info("JsonWriteObject", "Object %p class %s check_map %s", obj, cl ? cl->GetName() : "null", check_map ? "true" : "false");
Int_t special_kind = JsonSpecialClass(cl);
TString fObjectOutput, *fPrevOutput(0);
TJSONStackObj *stack = Stack();
if (stack && stack->fAccObjects && ((fValue.Length()>0) || (stack->fValues.GetLast()>=0))) {
if (fValue.Length()>0) {
stack->fValues.Add(new TObjString(fValue));
fValue.Clear();
}
fPrevOutput = fOutput;
fOutput = &fObjectOutput;
} else
if ((special_kind<=0) || (special_kind>100)) {
JsonDisablePostprocessing();
}
if (obj == 0) {
AppendOutput("null");
goto post_process;
}
if (special_kind<=0) {
if (check_map) {
std::map<const void *, unsigned>::const_iterator iter = fJsonrMap.find(obj);
if (iter != fJsonrMap.end()) {
AppendOutput(Form("\"$ref:%u\"", iter->second));
goto post_process;
}
fJsonrMap[obj] = fJsonrCnt;
}
fJsonrCnt++;
stack = PushStack(2);
AppendOutput("{", "\"_typename\"");
AppendOutput(fSemicolon.Data());
AppendOutput("\"");
AppendOutput(cl->GetName());
AppendOutput("\"");
} else {
stack = PushStack(0);
}
if (gDebug > 3)
Info("JsonWriteObject", "Starting object %p write for class: %s",
obj, cl->GetName());
stack->fAccObjects = special_kind < 10;
if (special_kind==-130)
JsonStreamCollection((TCollection *) obj, cl);
else
((TClass *)cl)->Streamer((void *)obj, *this);
if (gDebug > 3)
Info("JsonWriteObject", "Done object %p write for class: %s",
obj, cl->GetName());
if (special_kind==100) {
if (stack->fValues.GetLast() != 0)
Error("JsonWriteObject", "Problem when writing array");
stack->fValues.Delete();
} else if ((special_kind==110) || (special_kind==120)) {
if (stack->fValues.GetLast() > 1)
Error("JsonWriteObject", "Problem when writing TString or std::string");
stack->fValues.Delete();
AppendOutput(fValue.Data());
fValue.Clear();
} else if ((special_kind>0) && (special_kind<=TClassEdit::kBitSet)) {
if (stack->fValues.GetLast()<0) {
if (fValue!="0") Error("JsonWriteObject", "With empty stack fValue!=0");
fValue = "[]";
} else if (stack->fValues.GetLast() == 0) {
stack->fValues.Delete();
if (fValue.Length()==0) {
Error("JsonWriteObject", "Empty value when it should contain something");
fValue = "[]";
}
} else {
const char* separ = "[";
TString blob;
for (Int_t k=1;k<=stack->fValues.GetLast();k++) {
blob.Append(separ); separ = fArraySepar.Data();
blob.Append(stack->fValues.At(k)->GetName());
}
if (fValue.Length()>0) {
blob.Append(separ);
blob.Append(fValue);
}
blob.Append("]");
stack->fValues.Delete();
fValue = blob;
}
}
if ((special_kind==0) &&
((stack->fValues.GetLast() >= 0) || (fValue.Length()>0))) {
if (gDebug>0)
Info("JsonWriteObject", "Create blob value for class %s", cl->GetName());
AppendOutput(fArraySepar.Data(),"\"_blob\"");
AppendOutput(fSemicolon.Data());
const char* separ = "[";
for (Int_t k=0;k<=stack->fValues.GetLast();k++) {
AppendOutput(separ); separ = fArraySepar.Data();
AppendOutput(stack->fValues.At(k)->GetName());
}
if (fValue.Length()>0) {
AppendOutput(separ);
AppendOutput(fValue.Data());
}
AppendOutput("]");
fValue.Clear();
stack->fValues.Delete();
}
PopStack();
if (special_kind<=0) {
AppendOutput(0, "}");
}
post_process:
if (fPrevOutput!=0) {
fOutput = fPrevOutput;
if ((special_kind<=0) || (special_kind>100))
fValue = fObjectOutput;
else
if (fObjectOutput.Length()!=0)
Error("JsonWriteObject", "Non-empty object output for special class %s", cl->GetName());
}
}
void TBufferJSON::JsonStreamCollection(TCollection *col, const TClass *)
{
AppendOutput(",", "\"name\"");
AppendOutput(fSemicolon.Data());
AppendOutput("\"");
AppendOutput(col->GetName());
AppendOutput("\",", "\"arr\"");
AppendOutput(fSemicolon.Data());
AppendOutput("[");
bool islist = col->InheritsFrom(TList::Class());
TString sopt;
sopt.Capacity(500);
sopt = "[";
TIter iter(col);
TObject *obj;
Bool_t first = kTRUE;
while ((obj = iter()) != 0) {
if (!first) {
AppendOutput(fArraySepar.Data());
sopt.Append(fArraySepar.Data());
}
if (islist) {
sopt.Append("\"");
sopt.Append(iter.GetOption());
sopt.Append("\"");
}
JsonWriteObject(obj, obj->IsA());
first = kFALSE;
}
sopt.Append("]");
AppendOutput("]");
if (islist) {
AppendOutput(",", "\"opt\"");
AppendOutput(fSemicolon.Data());
AppendOutput(sopt.Data());
}
fValue.Clear();
}
void TBufferJSON::IncrementLevel(TVirtualStreamerInfo *info)
{
if (gDebug > 2)
Info("IncrementLevel", "Class: %s", (info ? info->GetClass()->GetName() : "custom"));
WorkWithClass((TStreamerInfo *)info);
}
void TBufferJSON::WorkWithClass(TStreamerInfo *sinfo, const TClass *cl)
{
fExpectedChain = kFALSE;
if (sinfo != 0) cl = sinfo->GetClass();
if (cl == 0) return;
if (gDebug > 3) Info("WorkWithClass", "Class: %s", cl->GetName());
TJSONStackObj *stack = Stack();
if ((stack != 0) && stack->IsStreamerElement() && !stack->fIsObjStarted &&
((stack->fElem->GetType() == TStreamerInfo::kObject) ||
(stack->fElem->GetType() == TStreamerInfo::kAny))) {
stack->fIsObjStarted = kTRUE;
fJsonrCnt++;
stack = PushStack(2);
AppendOutput("{", "\"_typename\"");
AppendOutput(fSemicolon.Data());
AppendOutput("\"");
AppendOutput(cl->GetName());
AppendOutput("\"");
} else {
stack = PushStack(0);
}
stack->fInfo = sinfo;
stack->fIsStreamerInfo = kTRUE;
}
void TBufferJSON::DecrementLevel(TVirtualStreamerInfo *info)
{
fExpectedChain = kFALSE;
if (gDebug > 2)
Info("DecrementLevel", "Class: %s",
(info ? info->GetClass()->GetName() : "custom"));
TJSONStackObj *stack = Stack();
if (stack->IsStreamerElement()) {
if (gDebug > 3)
Info("DecrementLevel", " Perform post-processing elem: %s",
stack->fElem->GetName());
PerformPostProcessing(stack);
stack = PopStack();
}
if (stack->fInfo != (TStreamerInfo *) info)
Error("DecrementLevel", " Mismatch of streamer info");
PopStack();
if (gDebug > 3)
Info("DecrementLevel", "Class: %s done",
(info ? info->GetClass()->GetName() : "custom"));
}
void TBufferJSON::SetStreamerElementNumber(TStreamerElement *elem, Int_t comp_type)
{
if (gDebug > 3)
Info("SetStreamerElementNumber", "Element name %s", elem->GetName());
WorkWithElement(elem, comp_type);
}
void TBufferJSON::WorkWithElement(TStreamerElement *elem, Int_t comp_type)
{
fExpectedChain = kFALSE;
TJSONStackObj *stack = Stack();
if (stack == 0) {
Error("WorkWithElement", "stack is empty");
return;
}
if (gDebug > 0)
Info("WorkWithElement", " Start element %s type %d typename %s",
elem ? elem->GetName() : "---", elem ? elem->GetType() : -1, elem ? elem->GetTypeName() : "---");
if (stack->IsStreamerElement()) {
if (gDebug > 3)
Info("WorkWithElement", " Perform post-processing elem: %s",
stack->fElem->GetName());
PerformPostProcessing(stack);
stack = PopStack();
}
fValue.Clear();
if (stack == 0) {
Error("WorkWithElement", "Lost of stack");
return;
}
TStreamerInfo *info = stack->fInfo;
if (!stack->IsStreamerInfo()) {
Error("WorkWithElement", "Problem in Inc/Dec level");
return;
}
Int_t number = info ? info->GetElements()->IndexOf(elem) : -1;
if (elem == 0) {
Error("WorkWithElement", "streamer info returns elem = 0");
return;
}
Bool_t isBasicType = (elem->GetType() > 0) && (elem->GetType() < 20);
fExpectedChain = isBasicType && (comp_type - elem->GetType() == TStreamerInfo::kOffsetL);
if (fExpectedChain && (gDebug > 3))
Info("WorkWithElement", " Expects chain for elem %s number %d",
elem->GetName(), number);
TClass *base_class = elem->IsBase() ? elem->GetClassPointer() : 0;
stack = PushStack(0);
stack->fElem = (TStreamerElement *) elem;
stack->fElemNumber = number;
stack->fIsElemOwner = (number < 0);
JsonStartElement(elem, base_class);
}
void TBufferJSON::ClassBegin(const TClass *cl, Version_t)
{
WorkWithClass(0, cl);
}
void TBufferJSON::ClassEnd(const TClass *)
{
DecrementLevel(0);
}
void TBufferJSON::ClassMember(const char *name, const char *typeName,
Int_t arrsize1, Int_t arrsize2)
{
if (typeName == 0) typeName = name;
if ((name == 0) || (strlen(name) == 0)) {
Error("ClassMember", "Invalid member name");
return;
}
TString tname = typeName;
Int_t typ_id = -1;
if (strcmp(typeName, "raw:data") == 0)
typ_id = TStreamerInfo::kMissing;
if (typ_id < 0) {
TDataType *dt = gROOT->GetType(typeName);
if (dt != 0)
if ((dt->GetType() > 0) && (dt->GetType() < 20))
typ_id = dt->GetType();
}
if (typ_id < 0)
if (strcmp(name, typeName) == 0) {
TClass *cl = TClass::GetClass(tname.Data());
if (cl != 0) typ_id = TStreamerInfo::kBase;
}
if (typ_id < 0) {
Bool_t isptr = kFALSE;
if (tname[tname.Length() - 1] == '*') {
tname.Resize(tname.Length() - 1);
isptr = kTRUE;
}
TClass *cl = TClass::GetClass(tname.Data());
if (cl == 0) {
Error("ClassMember", "Invalid class specifier %s", typeName);
return;
}
if (cl->IsTObject())
typ_id = isptr ? TStreamerInfo::kObjectp : TStreamerInfo::kObject;
else
typ_id = isptr ? TStreamerInfo::kAnyp : TStreamerInfo::kAny;
if ((cl == TString::Class()) && !isptr)
typ_id = TStreamerInfo::kTString;
}
TStreamerElement *elem = 0;
if (typ_id == TStreamerInfo::kMissing) {
elem = new TStreamerElement(name, "title", 0, typ_id, "raw:data");
} else if (typ_id == TStreamerInfo::kBase) {
TClass *cl = TClass::GetClass(tname.Data());
if (cl != 0) {
TStreamerBase *b = new TStreamerBase(tname.Data(), "title", 0);
b->SetBaseVersion(cl->GetClassVersion());
elem = b;
}
} else if ((typ_id > 0) && (typ_id < 20)) {
elem = new TStreamerBasicType(name, "title", 0, typ_id, typeName);
} else if ((typ_id == TStreamerInfo::kObject) ||
(typ_id == TStreamerInfo::kTObject) ||
(typ_id == TStreamerInfo::kTNamed)) {
elem = new TStreamerObject(name, "title", 0, tname.Data());
} else if (typ_id == TStreamerInfo::kObjectp) {
elem = new TStreamerObjectPointer(name, "title", 0, tname.Data());
} else if (typ_id == TStreamerInfo::kAny) {
elem = new TStreamerObjectAny(name, "title", 0, tname.Data());
} else if (typ_id == TStreamerInfo::kAnyp) {
elem = new TStreamerObjectAnyPointer(name, "title", 0, tname.Data());
} else if (typ_id == TStreamerInfo::kTString) {
elem = new TStreamerString(name, "title", 0);
}
if (elem == 0) {
Error("ClassMember", "Invalid combination name = %s type = %s",
name, typeName);
return;
}
if (arrsize1 > 0) {
elem->SetArrayDim(arrsize2 > 0 ? 2 : 1);
elem->SetMaxIndex(0, arrsize1);
if (arrsize2 > 0)
elem->SetMaxIndex(1, arrsize2);
}
WorkWithElement(elem, -1);
}
void TBufferJSON::PerformPostProcessing(TJSONStackObj *stack,
const TStreamerElement *elem)
{
if ((elem == 0) && stack->fIsPostProcessed) return;
if (elem == 0) elem = stack->fElem;
if (elem == 0) return;
if (gDebug > 3)
Info("PerformPostProcessing", "Element %s type %s",
elem->GetName(), elem->GetTypeName());
stack->fIsPostProcessed = kTRUE;
if (stack->fIsObjStarted) {
AppendOutput("", "}");
return;
}
const char *typname = elem->IsBase() ? elem->GetName() : elem->GetTypeName();
Bool_t isTObject = (elem->GetType() == TStreamerInfo::kTObject) || (strcmp("TObject", typname) == 0);
Bool_t isTString = elem->GetType() == TStreamerInfo::kTString;
Bool_t isSTLstring = elem->GetType() == TStreamerInfo::kSTLstring;
Bool_t isOffsetPArray = (elem->GetType() > TStreamerInfo::kOffsetP) && (elem->GetType() < TStreamerInfo::kOffsetP + 20);
Bool_t isTArray = (strncmp("TArray", typname, 6) == 0);
if (isTString || isSTLstring) {
if (gDebug > 3)
Info("PerformPostProcessing", "reformat string value = '%s'", fValue.Data());
stack->fValues.Delete();
} else if (isOffsetPArray) {
if ((stack->fValues.GetLast() < 0) && (fValue == "0")) {
fValue = "[]";
} else
if ((stack->fValues.GetLast() == 0) &&
(strcmp(stack->fValues.Last()->GetName(), "1") == 0)) {
stack->fValues.Delete();
} else {
Error("PerformPostProcessing", "Wrong values for kOffsetP type %s name %s",
typname, (elem ? elem->GetName() : "---"));
stack->fValues.Delete();
fValue = "[]";
}
} else if (isTObject) {
if (stack->fValues.GetLast() != 0) {
if (gDebug > 0)
Error("PerformPostProcessing", "When storing TObject, number of items %d not equal to 2", stack->fValues.GetLast());
AppendOutput(",", "\"dummy\"");
AppendOutput(fSemicolon.Data());
} else {
AppendOutput(",", "\"fUniqueID\"");
AppendOutput(fSemicolon.Data());
AppendOutput(stack->fValues.At(0)->GetName());
AppendOutput(",", "\"fBits\"");
AppendOutput(fSemicolon.Data());
}
stack->fValues.Delete();
} else if (isTArray) {
stack->fValues.Delete();
}
if (elem->IsBase() && (fValue.Length() == 0)) {
return;
}
if (stack->fValues.GetLast() >= 0) {
AppendOutput("[");
for (Int_t n = 0; n <= stack->fValues.GetLast(); n++) {
AppendOutput(stack->fValues.At(n)->GetName());
AppendOutput(fArraySepar.Data());
}
}
if (fValue.Length() == 0) {
AppendOutput("null");
} else {
AppendOutput(fValue.Data());
fValue.Clear();
}
if (stack->fValues.GetLast() >= 0)
AppendOutput("]");
}
TClass *TBufferJSON::ReadClass(const TClass *, UInt_t *)
{
return 0;
}
void TBufferJSON::WriteClass(const TClass *)
{
}
Int_t TBufferJSON::CheckByteCount(UInt_t , UInt_t ,
const TClass * )
{
return 0;
}
Int_t TBufferJSON::CheckByteCount(UInt_t, UInt_t, const char *)
{
return 0;
}
void TBufferJSON::SetByteCount(UInt_t, Bool_t)
{
}
void TBufferJSON::SkipVersion(const TClass *cl)
{
ReadVersion(0, 0, cl);
}
Version_t TBufferJSON::ReadVersion(UInt_t *start, UInt_t *bcnt,
const TClass * )
{
Version_t res = 0;
if (start) *start = 0;
if (bcnt) *bcnt = 0;
if (gDebug > 3) Info("ReadVersion", "Version = %d", res);
return res;
}
UInt_t TBufferJSON::WriteVersion(const TClass * , Bool_t )
{
return 0;
}
void *TBufferJSON::ReadObjectAny(const TClass *)
{
return 0;
}
void TBufferJSON::SkipObjectAny()
{
}
void TBufferJSON::WriteObjectClass(const void *actualObjStart,
const TClass *actualClass)
{
if (gDebug > 3)
Info("WriteObjectClass", "Class %s", (actualClass ? actualClass->GetName() : " null"));
JsonWriteObject(actualObjStart, actualClass);
}
#define TJSONPushValue() \
if (fValue.Length() > 0) Stack()->PushValue(fValue);
#define TBufferJSON_ReadArray(tname, vname) \
{ \
if (!vname) return 0; \
return 1; \
}
void TBufferJSON::ReadFloat16(Float_t *, TStreamerElement * )
{
}
void TBufferJSON::ReadDouble32(Double_t *, TStreamerElement * )
{
}
void TBufferJSON::ReadWithFactor(Float_t *, Double_t ,
Double_t )
{
}
void TBufferJSON::ReadWithNbits(Float_t *, Int_t )
{
}
void TBufferJSON::ReadWithFactor(Double_t *, Double_t ,
Double_t )
{
}
void TBufferJSON::ReadWithNbits(Double_t *, Int_t )
{
}
void TBufferJSON::WriteFloat16(Float_t *f, TStreamerElement * )
{
TJSONPushValue();
JsonWriteBasic(*f);
}
void TBufferJSON::WriteDouble32(Double_t *d, TStreamerElement * )
{
TJSONPushValue();
JsonWriteBasic(*d);
}
Int_t TBufferJSON::ReadArray(Bool_t *&b)
{
TBufferJSON_ReadArray(Bool_t, b);
}
Int_t TBufferJSON::ReadArray(Char_t *&c)
{
TBufferJSON_ReadArray(Char_t, c);
}
Int_t TBufferJSON::ReadArray(UChar_t *&c)
{
TBufferJSON_ReadArray(UChar_t, c);
}
Int_t TBufferJSON::ReadArray(Short_t *&h)
{
TBufferJSON_ReadArray(Short_t, h);
}
Int_t TBufferJSON::ReadArray(UShort_t *&h)
{
TBufferJSON_ReadArray(UShort_t, h);
}
Int_t TBufferJSON::ReadArray(Int_t *&i)
{
TBufferJSON_ReadArray(Int_t, i);
}
Int_t TBufferJSON::ReadArray(UInt_t *&i)
{
TBufferJSON_ReadArray(UInt_t, i);
}
Int_t TBufferJSON::ReadArray(Long_t *&l)
{
TBufferJSON_ReadArray(Long_t, l);
}
Int_t TBufferJSON::ReadArray(ULong_t *&l)
{
TBufferJSON_ReadArray(ULong_t, l);
}
Int_t TBufferJSON::ReadArray(Long64_t *&l)
{
TBufferJSON_ReadArray(Long64_t, l);
}
Int_t TBufferJSON::ReadArray(ULong64_t *&l)
{
TBufferJSON_ReadArray(ULong64_t, l);
}
Int_t TBufferJSON::ReadArray(Float_t *&f)
{
TBufferJSON_ReadArray(Float_t, f);
}
Int_t TBufferJSON::ReadArray(Double_t *&d)
{
TBufferJSON_ReadArray(Double_t, d);
}
Int_t TBufferJSON::ReadArrayFloat16(Float_t *&f, TStreamerElement * )
{
TBufferJSON_ReadArray(Float_t, f);
}
Int_t TBufferJSON::ReadArrayDouble32(Double_t *&d, TStreamerElement * )
{
TBufferJSON_ReadArray(Double_t, d);
}
#define TBufferJSON_ReadStaticArray(vname) \
{ \
if (!vname) return 0; \
return 1; \
}
Int_t TBufferJSON::ReadStaticArray(Bool_t *b)
{
TBufferJSON_ReadStaticArray(b);
}
Int_t TBufferJSON::ReadStaticArray(Char_t *c)
{
TBufferJSON_ReadStaticArray(c);
}
Int_t TBufferJSON::ReadStaticArray(UChar_t *c)
{
TBufferJSON_ReadStaticArray(c);
}
Int_t TBufferJSON::ReadStaticArray(Short_t *h)
{
TBufferJSON_ReadStaticArray(h);
}
Int_t TBufferJSON::ReadStaticArray(UShort_t *h)
{
TBufferJSON_ReadStaticArray(h);
}
Int_t TBufferJSON::ReadStaticArray(Int_t *i)
{
TBufferJSON_ReadStaticArray(i);
}
Int_t TBufferJSON::ReadStaticArray(UInt_t *i)
{
TBufferJSON_ReadStaticArray(i);
}
Int_t TBufferJSON::ReadStaticArray(Long_t *l)
{
TBufferJSON_ReadStaticArray(l);
}
Int_t TBufferJSON::ReadStaticArray(ULong_t *l)
{
TBufferJSON_ReadStaticArray(l);
}
Int_t TBufferJSON::ReadStaticArray(Long64_t *l)
{
TBufferJSON_ReadStaticArray(l);
}
Int_t TBufferJSON::ReadStaticArray(ULong64_t *l)
{
TBufferJSON_ReadStaticArray(l);
}
Int_t TBufferJSON::ReadStaticArray(Float_t *f)
{
TBufferJSON_ReadStaticArray(f);
}
Int_t TBufferJSON::ReadStaticArray(Double_t *d)
{
TBufferJSON_ReadStaticArray(d);
}
Int_t TBufferJSON::ReadStaticArrayFloat16(Float_t *f, TStreamerElement * )
{
TBufferJSON_ReadStaticArray(f);
}
Int_t TBufferJSON::ReadStaticArrayDouble32(Double_t *d, TStreamerElement * )
{
TBufferJSON_ReadStaticArray(d);
}
#define TBufferJSON_ReadFastArray(vname) \
{ \
if (n <= 0) return; \
if (!vname) return; \
}
void TBufferJSON::ReadFastArray(Bool_t *b, Int_t n)
{
TBufferJSON_ReadFastArray(b);
}
void TBufferJSON::ReadFastArray(Char_t *c, Int_t n)
{
TBufferJSON_ReadFastArray(c);
}
void TBufferJSON::ReadFastArrayString(Char_t *c, Int_t n)
{
TBufferJSON_ReadFastArray(c);
}
void TBufferJSON::ReadFastArray(UChar_t *c, Int_t n)
{
TBufferJSON_ReadFastArray(c);
}
void TBufferJSON::ReadFastArray(Short_t *h, Int_t n)
{
TBufferJSON_ReadFastArray(h);
}
void TBufferJSON::ReadFastArray(UShort_t *h, Int_t n)
{
TBufferJSON_ReadFastArray(h);
}
void TBufferJSON::ReadFastArray(Int_t *i, Int_t n)
{
TBufferJSON_ReadFastArray(i);
}
void TBufferJSON::ReadFastArray(UInt_t *i, Int_t n)
{
TBufferJSON_ReadFastArray(i);
}
void TBufferJSON::ReadFastArray(Long_t *l, Int_t n)
{
TBufferJSON_ReadFastArray(l);
}
void TBufferJSON::ReadFastArray(ULong_t *l, Int_t n)
{
TBufferJSON_ReadFastArray(l);
}
void TBufferJSON::ReadFastArray(Long64_t *l, Int_t n)
{
TBufferJSON_ReadFastArray(l);
}
void TBufferJSON::ReadFastArray(ULong64_t *l, Int_t n)
{
TBufferJSON_ReadFastArray(l);
}
void TBufferJSON::ReadFastArray(Float_t *f, Int_t n)
{
TBufferJSON_ReadFastArray(f);
}
void TBufferJSON::ReadFastArray(Double_t *d, Int_t n)
{
TBufferJSON_ReadFastArray(d);
}
void TBufferJSON::ReadFastArrayFloat16(Float_t *f, Int_t n,
TStreamerElement * )
{
TBufferJSON_ReadFastArray(f);
}
void TBufferJSON::ReadFastArrayWithFactor(Float_t *f, Int_t n,
Double_t ,
Double_t )
{
TBufferJSON_ReadFastArray(f);
}
void TBufferJSON::ReadFastArrayWithNbits(Float_t *f, Int_t n, Int_t )
{
TBufferJSON_ReadFastArray(f);
}
void TBufferJSON::ReadFastArrayDouble32(Double_t *d, Int_t n,
TStreamerElement * )
{
TBufferJSON_ReadFastArray(d);
}
void TBufferJSON::ReadFastArrayWithFactor(Double_t *d, Int_t n,
Double_t ,
Double_t )
{
TBufferJSON_ReadFastArray(d);
}
void TBufferJSON::ReadFastArrayWithNbits(Double_t *d, Int_t n, Int_t )
{
TBufferJSON_ReadFastArray(d);
}
void TBufferJSON::ReadFastArray(void * , const TClass * ,
Int_t , TMemberStreamer * ,
const TClass * )
{
}
void TBufferJSON::ReadFastArray(void ** , const TClass * ,
Int_t , Bool_t ,
TMemberStreamer * ,
const TClass * )
{
}
#define TJSONWriteArrayContent(vname, arrsize) \
{ \
fValue.Append("["); \
for (Int_t indx=0;indx<arrsize;indx++) { \
if (indx>0) fValue.Append(fArraySepar.Data()); \
JsonWriteBasic(vname[indx]); \
} \
fValue.Append("]"); \
}
#define TBufferJSON_WriteArray(vname) \
{ \
TJSONPushValue(); \
TJSONWriteArrayContent(vname, n); \
}
void TBufferJSON::WriteArray(const Bool_t *b, Int_t n)
{
TBufferJSON_WriteArray(b);
}
void TBufferJSON::WriteArray(const Char_t *c, Int_t n)
{
TBufferJSON_WriteArray(c);
}
void TBufferJSON::WriteArray(const UChar_t *c, Int_t n)
{
TBufferJSON_WriteArray(c);
}
void TBufferJSON::WriteArray(const Short_t *h, Int_t n)
{
TBufferJSON_WriteArray(h);
}
void TBufferJSON::WriteArray(const UShort_t *h, Int_t n)
{
TBufferJSON_WriteArray(h);
}
void TBufferJSON::WriteArray(const Int_t *i, Int_t n)
{
TBufferJSON_WriteArray(i);
}
void TBufferJSON::WriteArray(const UInt_t *i, Int_t n)
{
TBufferJSON_WriteArray(i);
}
void TBufferJSON::WriteArray(const Long_t *l, Int_t n)
{
TBufferJSON_WriteArray(l);
}
void TBufferJSON::WriteArray(const ULong_t *l, Int_t n)
{
TBufferJSON_WriteArray(l);
}
void TBufferJSON::WriteArray(const Long64_t *l, Int_t n)
{
TBufferJSON_WriteArray(l);
}
void TBufferJSON::WriteArray(const ULong64_t *l, Int_t n)
{
TBufferJSON_WriteArray(l);
}
void TBufferJSON::WriteArray(const Float_t *f, Int_t n)
{
TBufferJSON_WriteArray(f);
}
void TBufferJSON::WriteArray(const Double_t *d, Int_t n)
{
TBufferJSON_WriteArray(d);
}
void TBufferJSON::WriteArrayFloat16(const Float_t *f, Int_t n,
TStreamerElement * )
{
TBufferJSON_WriteArray(f);
}
void TBufferJSON::WriteArrayDouble32(const Double_t *d, Int_t n,
TStreamerElement * )
{
TBufferJSON_WriteArray(d);
}
#define TBufferJSON_WriteFastArray(vname) \
{ \
TJSONPushValue(); \
if (n <= 0) { fValue.Append("[]"); return; } \
TStreamerElement* elem = Stack(0)->fElem; \
if ((elem != 0) && (elem->GetType()>TStreamerInfo::kOffsetL) && \
(elem->GetType() < TStreamerInfo::kOffsetP) && \
(elem->GetArrayLength() != n)) fExpectedChain = kTRUE; \
if (fExpectedChain) { \
TStreamerInfo* info = Stack(1)->fInfo; \
Int_t startnumber = Stack(0)->fElemNumber; \
fExpectedChain = kFALSE; \
Int_t index(0); \
while (index<n) { \
elem = (TStreamerElement*)info->GetElements()->At(startnumber++);\
if (index>0) JsonStartElement(elem); \
if (elem->GetType()<TStreamerInfo::kOffsetL) { \
JsonWriteBasic(vname[index]); \
index++; \
} else { \
TJSONWriteArrayContent((vname+index), elem->GetArrayLength());\
index+=elem->GetArrayLength(); \
} \
PerformPostProcessing(Stack(0), elem); \
} \
} \
else { \
TJSONWriteArrayContent(vname, n); \
} \
}
void TBufferJSON::WriteFastArray(const Bool_t *b, Int_t n)
{
TBufferJSON_WriteFastArray(b);
}
void TBufferJSON::WriteFastArray(const Char_t *c, Int_t n)
{
Bool_t usedefault = fExpectedChain;
const Char_t *buf = c;
if (!usedefault)
for (int i = 0; i < n; i++) {
if (*buf < 27) {
usedefault = kTRUE;
break;
}
buf++;
}
if (usedefault) {
TBufferJSON_WriteFastArray(c);
} else {
TJSONPushValue();
fValue.Append("\"");
if ((c != 0) && (n > 0)) fValue.Append(c, n);
fValue.Append("\"");
}
}
void TBufferJSON::WriteFastArrayString(const Char_t *c, Int_t n)
{
WriteFastArray(c, n);
}
void TBufferJSON::WriteFastArray(const UChar_t *c, Int_t n)
{
TBufferJSON_WriteFastArray(c);
}
void TBufferJSON::WriteFastArray(const Short_t *h, Int_t n)
{
TBufferJSON_WriteFastArray(h);
}
void TBufferJSON::WriteFastArray(const UShort_t *h, Int_t n)
{
TBufferJSON_WriteFastArray(h);
}
void TBufferJSON::WriteFastArray(const Int_t *i, Int_t n)
{
TBufferJSON_WriteFastArray(i);
}
void TBufferJSON::WriteFastArray(const UInt_t *i, Int_t n)
{
TBufferJSON_WriteFastArray(i);
}
void TBufferJSON::WriteFastArray(const Long_t *l, Int_t n)
{
TBufferJSON_WriteFastArray(l);
}
void TBufferJSON::WriteFastArray(const ULong_t *l, Int_t n)
{
TBufferJSON_WriteFastArray(l);
}
void TBufferJSON::WriteFastArray(const Long64_t *l, Int_t n)
{
TBufferJSON_WriteFastArray(l);
}
void TBufferJSON::WriteFastArray(const ULong64_t *l, Int_t n)
{
TBufferJSON_WriteFastArray(l);
}
void TBufferJSON::WriteFastArray(const Float_t *f, Int_t n)
{
TBufferJSON_WriteFastArray(f);
}
void TBufferJSON::WriteFastArray(const Double_t *d, Int_t n)
{
TBufferJSON_WriteFastArray(d);
}
void TBufferJSON::WriteFastArrayFloat16(const Float_t *f, Int_t n,
TStreamerElement * )
{
TBufferJSON_WriteFastArray(f);
}
void TBufferJSON::WriteFastArrayDouble32(const Double_t *d, Int_t n,
TStreamerElement * )
{
TBufferJSON_WriteFastArray(d);
}
void TBufferJSON::WriteFastArray(void *start, const TClass *cl, Int_t n,
TMemberStreamer *streamer)
{
if (gDebug > 2)
Info("WriteFastArray", "void *start cl %s n %d streamer %p",
cl ? cl->GetName() : "---", n, streamer);
if (streamer) {
JsonDisablePostprocessing();
(*streamer)(*this, start, 0);
return;
}
char *obj = (char *)start;
if (!n) n = 1;
int size = cl->Size();
if (n > 1) {
JsonDisablePostprocessing();
AppendOutput("[");
}
for (Int_t j = 0; j < n; j++, obj += size) {
if (j > 0) AppendOutput(fArraySepar.Data());
JsonWriteObject(obj, cl, kFALSE);
}
if (n > 1) {
AppendOutput("]");
}
}
Int_t TBufferJSON::WriteFastArray(void **start, const TClass *cl, Int_t n,
Bool_t isPreAlloc, TMemberStreamer *streamer)
{
if (gDebug > 2)
Info("WriteFastArray", "void **startp cl %s n %d streamer %p",
cl->GetName(), n, streamer);
if (streamer) {
JsonDisablePostprocessing();
(*streamer)(*this, (void *)start, 0);
return 0;
}
Int_t res = 0;
if (n > 1) {
JsonDisablePostprocessing();
AppendOutput("[");
}
if (!isPreAlloc) {
for (Int_t j = 0; j < n; j++) {
if (j > 0) AppendOutput(fArraySepar.Data());
res |= WriteObjectAny(start[j], cl);
}
} else {
for (Int_t j = 0; j < n; j++) {
if (j > 0) AppendOutput(fArraySepar.Data());
if (!start[j]) start[j] = ((TClass *)cl)->New();
JsonWriteObject(start[j], cl, kFALSE);
}
}
if (n > 1) {
AppendOutput("]");
}
return res;
}
void TBufferJSON::StreamObject(void *obj, const type_info &typeinfo,
const TClass * )
{
StreamObject(obj, TClass::GetClass(typeinfo));
}
void TBufferJSON::StreamObject(void *obj, const char *className,
const TClass * )
{
StreamObject(obj, TClass::GetClass(className));
}
void TBufferJSON::StreamObject(TObject *obj)
{
StreamObject(obj, obj ? obj->IsA() : TObject::Class());
}
void TBufferJSON::StreamObject(void *obj, const TClass *cl,
const TClass * )
{
if (gDebug > 3)
Info("StreamObject", "Class: %s", (cl ? cl->GetName() : "none"));
JsonWriteObject(obj, cl);
}
void TBufferJSON::ReadBool(Bool_t &)
{
}
void TBufferJSON::ReadChar(Char_t &)
{
}
void TBufferJSON::ReadUChar(UChar_t &)
{
}
void TBufferJSON::ReadShort(Short_t &)
{
}
void TBufferJSON::ReadUShort(UShort_t &)
{
}
void TBufferJSON::ReadInt(Int_t &)
{
}
void TBufferJSON::ReadUInt(UInt_t &)
{
}
void TBufferJSON::ReadLong(Long_t &)
{
}
void TBufferJSON::ReadULong(ULong_t &)
{
}
void TBufferJSON::ReadLong64(Long64_t &)
{
}
void TBufferJSON::ReadULong64(ULong64_t &)
{
}
void TBufferJSON::ReadFloat(Float_t &)
{
}
void TBufferJSON::ReadDouble(Double_t &)
{
}
void TBufferJSON::ReadCharP(Char_t *)
{
}
void TBufferJSON::ReadTString(TString & )
{
}
void TBufferJSON::WriteBool(Bool_t b)
{
TJSONPushValue();
JsonWriteBasic(b);
}
void TBufferJSON::WriteChar(Char_t c)
{
TJSONPushValue();
JsonWriteBasic(c);
}
void TBufferJSON::WriteUChar(UChar_t c)
{
TJSONPushValue();
JsonWriteBasic(c);
}
void TBufferJSON::WriteShort(Short_t h)
{
TJSONPushValue();
JsonWriteBasic(h);
}
void TBufferJSON::WriteUShort(UShort_t h)
{
TJSONPushValue();
JsonWriteBasic(h);
}
void TBufferJSON::WriteInt(Int_t i)
{
TJSONPushValue();
JsonWriteBasic(i);
}
void TBufferJSON::WriteUInt(UInt_t i)
{
TJSONPushValue();
JsonWriteBasic(i);
}
void TBufferJSON::WriteLong(Long_t l)
{
TJSONPushValue();
JsonWriteBasic(l);
}
void TBufferJSON::WriteULong(ULong_t l)
{
TJSONPushValue();
JsonWriteBasic(l);
}
void TBufferJSON::WriteLong64(Long64_t l)
{
TJSONPushValue();
JsonWriteBasic(l);
}
void TBufferJSON::WriteULong64(ULong64_t l)
{
TJSONPushValue();
JsonWriteBasic(l);
}
void TBufferJSON::WriteFloat(Float_t f)
{
TJSONPushValue();
JsonWriteBasic(f);
}
void TBufferJSON::WriteDouble(Double_t d)
{
TJSONPushValue();
JsonWriteBasic(d);
}
void TBufferJSON::WriteCharP(const Char_t *c)
{
TJSONPushValue();
fValue.Append("\"");
fValue.Append(c);
fValue.Append("\"");
}
void TBufferJSON::WriteTString(const TString &s)
{
Info("WriteTString", "Write string value");
TJSONPushValue();
fValue.Append("\"");
fValue.Append(s);
fValue.Append("\"");
}
void TBufferJSON::JsonWriteBasic(Char_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%d", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(Short_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%hd", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(Int_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%d", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(Long_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%ld", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(Long64_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), FLong64, value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(Float_t value)
{
char buf[200];
snprintf(buf, sizeof(buf), fgFloatFmt, value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(Double_t value)
{
char buf[1000];
snprintf(buf, sizeof(buf), fgFloatFmt, value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(Bool_t value)
{
fValue.Append(value ? "true" : "false");
}
void TBufferJSON::JsonWriteBasic(UChar_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%u", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(UShort_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%hu", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(UInt_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%u", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(ULong_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), "%lu", value);
fValue.Append(buf);
}
void TBufferJSON::JsonWriteBasic(ULong64_t value)
{
char buf[50];
snprintf(buf, sizeof(buf), FULong64, value);
fValue.Append(buf);
}
void TBufferJSON::SetFloatFormat(const char *fmt)
{
if (fmt == 0) fmt = "%e";
fgFloatFmt = fmt;
}
const char *TBufferJSON::GetFloatFormat()
{
return fgFloatFmt;
}
Int_t TBufferJSON::ApplySequence(const TStreamerInfoActions::TActionSequence &sequence,
void *obj)
{
TVirtualStreamerInfo *info = sequence.fStreamerInfo;
IncrementLevel(info);
if (gDebug) {
TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
iter != end; ++iter) {
SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem,(*iter).fConfiguration->fCompInfo->fType);
(*iter).PrintDebug(*this, obj);
(*iter)(*this, obj);
}
} else {
TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
iter != end; ++iter) {
SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem,(*iter).fConfiguration->fCompInfo->fType);
(*iter)(*this, obj);
}
}
DecrementLevel(info);
return 0;
}
Int_t TBufferJSON::ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence,
void *start_collection, void *end_collection)
{
TVirtualStreamerInfo *info = sequence.fStreamerInfo;
IncrementLevel(info);
if (gDebug) {
TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
iter != end; ++iter) {
SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem,(*iter).fConfiguration->fCompInfo->fType);
(*iter).PrintDebug(*this, *(char **)start_collection);
(*iter)(*this, start_collection, end_collection);
}
} else {
TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
iter != end; ++iter) {
SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem,(*iter).fConfiguration->fCompInfo->fType);
(*iter)(*this, start_collection, end_collection);
}
}
DecrementLevel(info);
return 0;
}
Int_t TBufferJSON::ApplySequence(const TStreamerInfoActions::TActionSequence &sequence,
void *start_collection, void *end_collection)
{
TVirtualStreamerInfo *info = sequence.fStreamerInfo;
IncrementLevel(info);
TStreamerInfoActions::TLoopConfiguration *loopconfig = sequence.fLoopConfig;
if (gDebug) {
void *arr0 = loopconfig->GetFirstAddress(start_collection, end_collection);
TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
iter != end; ++iter) {
SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem,(*iter).fConfiguration->fCompInfo->fType);
(*iter).PrintDebug(*this, arr0);
(*iter)(*this, start_collection, end_collection, loopconfig);
}
} else {
TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
for (TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
iter != end; ++iter) {
SetStreamerElementNumber((*iter).fConfiguration->fCompInfo->fElem,(*iter).fConfiguration->fCompInfo->fType);
(*iter)(*this, start_collection, end_collection, loopconfig);
}
}
DecrementLevel(info);
return 0;
}
Int_t TBufferJSON::WriteClones(TClonesArray *a, Int_t )
{
Info("WriteClones", "Not yet tested");
if (a != 0)
JsonStreamCollection(a, a->IsA());
return 0;
}
namespace {
struct DynamicType {
virtual ~DynamicType() {}
};
}
Int_t TBufferJSON::WriteObjectAny(const void *obj, const TClass *ptrClass)
{
if (!obj) {
WriteObjectClass(0, 0);
return 1;
}
if (!ptrClass) {
Error("WriteObjectAny", "ptrClass argument may not be 0");
return 0;
}
TClass *clActual = ptrClass->GetActualClass(obj);
if (clActual == 0) {
DynamicType *d_ptr = (DynamicType *)obj;
Warning("WriteObjectAny",
"An object of type %s (from type_info) passed through a %s pointer was truncated (due a missing dictionary)!!!",
typeid(*d_ptr).name(), ptrClass->GetName());
WriteObjectClass(obj, ptrClass);
return 2;
} else if (clActual && (clActual != ptrClass)) {
const char *temp = (const char *) obj;
temp -= clActual->GetBaseClassOffset(ptrClass);
WriteObjectClass(temp, clActual);
return 1;
} else {
WriteObjectClass(obj, ptrClass);
return 1;
}
}
Int_t TBufferJSON::WriteClassBuffer(const TClass *cl, void *pointer)
{
TStreamerInfo *sinfo = (TStreamerInfo *)const_cast<TClass *>(cl)->GetCurrentStreamerInfo();
if (sinfo == 0) {
R__LOCKGUARD(gInterpreterMutex);
sinfo = (TStreamerInfo*)const_cast<TClass*>(cl)->GetCurrentStreamerInfo();
if(sinfo == 0) {
const_cast<TClass *>(cl)->BuildRealData(pointer);
sinfo = new TStreamerInfo(const_cast<TClass *>(cl));
const_cast<TClass *>(cl)->SetCurrentStreamerInfo(sinfo);
const_cast<TClass *>(cl)->RegisterStreamerInfo(sinfo);
if (gDebug > 0)
printf("Creating StreamerInfo for class: %s, version: %d\n",
cl->GetName(), cl->GetClassVersion());
sinfo->Build();
}
} else if (!sinfo->IsCompiled()) {
R__LOCKGUARD(gInterpreterMutex);
if (!sinfo->IsCompiled()) {
const_cast<TClass *>(cl)->BuildRealData(pointer);
sinfo->BuildOld();
}
}
TagStreamerInfo(sinfo);
ApplySequence(*(sinfo->GetWriteObjectWiseActions()), (char *)pointer);
if (gDebug > 2)
Info("WriteClassBuffer", "class: %s version %d done", cl->GetName(), cl->GetClassVersion());
return 0;
}