116 TXMLFile::TXMLFile(
const char *filename, Option_t *option,
const char *title, Int_t compression)
119 ::Fatal(
"TFile::TFile",
"ROOT system not initialized");
121 fXML = std::make_unique<TXMLEngine>();
123 if (filename && !strncmp(filename,
"xml:", 4))
126 gDirectory =
nullptr;
129 TDirectoryFile::Build(
this, 0);
134 fVersion = gROOT->GetVersionInt();
137 SetCompressionSettings(compression);
146 fProcessIDs =
nullptr;
148 fIOVersion = TXMLFile::Class_Version();
149 SetBit(kBinaryFile, kFALSE);
154 if (fOption ==
"NEW")
157 Bool_t create = (fOption ==
"CREATE") ? kTRUE : kFALSE;
158 Bool_t recreate = (fOption ==
"RECREATE") ? kTRUE : kFALSE;
159 Bool_t update = (fOption ==
"UPDATE") ? kTRUE : kFALSE;
160 Bool_t read = (fOption ==
"READ") ? kTRUE : kFALSE;
161 Bool_t xmlsetup = IsValidXmlSetup(option);
165 if (!create && !recreate && !update && !read) {
170 Bool_t devnull = kFALSE;
171 const char *fname =
nullptr;
173 if (!filename || !filename[0]) {
174 Error(
"TXMLFile",
"file name is not specified");
179 if (!strcmp(filename,
"/dev/null") && !gSystem->AccessPathName(filename, kWritePermission)) {
186 SetBit(TFile::kDevNull);
191 fname = gSystem->ExpandPathName(filename);
194 delete[](
char *) fname;
197 Error(
"TXMLFile",
"error expanding path %s", filename);
202 if (!gSystem->AccessPathName(fname, kFileExists))
203 gSystem->Unlink(fname);
209 if (create && !devnull && !gSystem->AccessPathName(fname, kFileExists)) {
210 Error(
"TXMLFile",
"file %s already exists", fname);
215 if (gSystem->AccessPathName(fname, kFileExists)) {
219 if (update && gSystem->AccessPathName(fname, kWritePermission)) {
220 Error(
"TXMLFile",
"no write permission, could not open file %s", fname);
226 if (gSystem->AccessPathName(fname, kFileExists)) {
227 Error(
"TXMLFile",
"file %s does not exist", fname);
230 if (gSystem->AccessPathName(fname, kReadPermission)) {
231 Error(
"TXMLFile",
"no read permission, could not open file %s", fname);
238 if (create || update)
245 ReadSetupFromStr(option);
247 ReadSetupFromStr(TXMLSetup::DefaultXmlSetup());
263 void TXMLFile::InitXmlFile(Bool_t create)
265 Int_t len = gROOT->GetListOfStreamerInfo()->GetSize() + 1;
268 fClassIndex =
new TArrayC(len);
269 fClassIndex->Reset(0);
272 fDoc = fXML->NewDoc();
273 XMLNodePointer_t fRootNode = fXML->NewChild(
nullptr,
nullptr, xmlio::Root);
274 fXML->DocSetRootElement(fDoc, fRootNode);
280 R__LOCKGUARD(gROOTMutex);
281 gROOT->GetListOfFiles()->Add(
this);
288 while ((key = (TKey *)iter()) !=
nullptr) {
289 if (!strcmp(key->GetClassName(),
"TProcessID"))
293 fProcessIDs =
new TObjArray(fNProcessIDs + 1);
300 void TXMLFile::Close(Option_t *option)
305 TString opt = option;
306 if (opt.Length() > 0)
321 fClassIndex =
nullptr;
324 if (fStreamerInfoNode) {
325 fXML->FreeNode(fStreamerInfoNode);
326 fStreamerInfoNode =
nullptr;
330 TDirectory::TContext ctxt(
this);
332 TDirectoryFile::Close();
337 TIter next(fProcessIDs);
339 while ((pid = (TProcessID *)next())) {
340 if (!pid->DecrementCount()) {
341 if (pid != TProcessID::GetSessionProcessID())
343 }
else if (opt.Contains(
"r")) {
349 R__LOCKGUARD(gROOTMutex);
350 gROOT->GetListOfFiles()->Remove(
this);
356 TXMLFile::~TXMLFile()
364 Bool_t TXMLFile::IsOpen()
const
366 return fDoc !=
nullptr;
373 Int_t TXMLFile::ReOpen(Option_t *mode)
380 if (opt !=
"READ" && opt !=
"UPDATE") {
381 Error(
"ReOpen",
"mode must be either READ or UPDATE, not %s", opt.Data());
385 if (opt == fOption || (opt ==
"UPDATE" && fOption ==
"CREATE"))
391 if (IsOpen() && IsWritable())
409 TKey *TXMLFile::CreateKey(TDirectory *mother,
const TObject *obj,
const char *name, Int_t)
411 return new TKeyXML(mother, ++fKeyCounter, obj, name);
417 TKey *TXMLFile::CreateKey(TDirectory *mother,
const void *obj,
const TClass *cl,
const char *name, Int_t)
419 return new TKeyXML(mother, ++fKeyCounter, obj, cl, name);
425 void TXMLFile::ProduceFileNames(
const char *filename, TString &fname, TString &dtdname)
430 Bool_t hasxmlext = kFALSE;
432 if (fname.Length() > 4) {
433 TString last = fname(fname.Length() - 4, 4);
435 hasxmlext = (last ==
".xml");
439 dtdname.Replace(dtdname.Length() - 4, 4,
".dtd");
455 void TXMLFile::SaveToFile()
461 Info(
"SaveToFile",
"File: %s", fRealName.Data());
463 XMLNodePointer_t fRootNode = fXML->DocGetRootElement(fDoc);
465 fXML->FreeAttr(fRootNode, xmlio::Setup);
466 fXML->NewAttr(fRootNode,
nullptr, xmlio::Setup, GetSetupAsString());
468 fXML->FreeAttr(fRootNode, xmlio::Ref);
469 fXML->NewAttr(fRootNode,
nullptr, xmlio::Ref, xmlio::Null);
471 if (GetIOVersion() > 1) {
473 fXML->FreeAttr(fRootNode, xmlio::CreateTm);
474 if (TestBit(TFile::kReproducible))
475 fXML->NewAttr(fRootNode,
nullptr, xmlio::CreateTm, TDatime((UInt_t) 1).AsSQLString());
477 fXML->NewAttr(fRootNode,
nullptr, xmlio::CreateTm, fDatimeC.AsSQLString());
479 fXML->FreeAttr(fRootNode, xmlio::ModifyTm);
480 if (TestBit(TFile::kReproducible))
481 fXML->NewAttr(fRootNode,
nullptr, xmlio::ModifyTm, TDatime((UInt_t) 1).AsSQLString());
483 fXML->NewAttr(fRootNode,
nullptr, xmlio::ModifyTm, fDatimeM.AsSQLString());
485 fXML->FreeAttr(fRootNode, xmlio::ObjectUUID);
486 if (TestBit(TFile::kReproducible))
487 fXML->NewAttr(fRootNode,
nullptr, xmlio::ObjectUUID, TUUID(
"00000000-0000-0000-0000-000000000000").AsString());
489 fXML->NewAttr(fRootNode,
nullptr, xmlio::ObjectUUID, fUUID.AsString());
491 fXML->FreeAttr(fRootNode, xmlio::Title);
492 if (strlen(GetTitle()) > 0)
493 fXML->NewAttr(fRootNode,
nullptr, xmlio::Title, GetTitle());
495 fXML->FreeAttr(fRootNode, xmlio::IOVersion);
496 fXML->NewIntAttr(fRootNode, xmlio::IOVersion, GetIOVersion());
498 fXML->FreeAttr(fRootNode,
"file_version");
499 fXML->NewIntAttr(fRootNode,
"file_version", fVersion);
502 TString fname, dtdname;
503 ProduceFileNames(fRealName, fname, dtdname);
512 CombineNodesTree(
this, fRootNode, kTRUE);
516 if (fStreamerInfoNode)
517 fXML->AddChild(fRootNode, fStreamerInfoNode);
519 Int_t layout = GetCompressionLevel() > 5 ? 0 : 1;
521 fXML->SaveDoc(fDoc, fname, layout);
527 CombineNodesTree(
this, fRootNode, kFALSE);
529 if (fStreamerInfoNode)
530 fXML->UnlinkNode(fStreamerInfoNode);
536 void TXMLFile::CombineNodesTree(TDirectory *dir, XMLNodePointer_t topnode, Bool_t dolink)
541 TIter iter(dir->GetListOfKeys());
542 TKeyXML *key =
nullptr;
544 while ((key = (TKeyXML *)iter()) !=
nullptr) {
546 fXML->AddChild(topnode, key->KeyNode());
548 fXML->UnlinkNode(key->KeyNode());
550 CombineNodesTree(FindKeyDir(dir, key->GetKeyId()), key->KeyNode(), dolink);
560 Bool_t TXMLFile::ReadFromFile()
562 fDoc = fXML->ParseFile(fRealName);
566 XMLNodePointer_t fRootNode = fXML->DocGetRootElement(fDoc);
568 if (!fRootNode || !fXML->ValidateVersion(fDoc)) {
574 ReadSetupFromStr(fXML->GetAttr(fRootNode, xmlio::Setup));
576 if (fXML->HasAttr(fRootNode, xmlio::CreateTm)) {
577 TDatime tm(fXML->GetAttr(fRootNode, xmlio::CreateTm));
581 if (fXML->HasAttr(fRootNode, xmlio::ModifyTm)) {
582 TDatime tm(fXML->GetAttr(fRootNode, xmlio::ModifyTm));
586 if (fXML->HasAttr(fRootNode, xmlio::ObjectUUID)) {
587 TUUID id(fXML->GetAttr(fRootNode, xmlio::ObjectUUID));
591 if (fXML->HasAttr(fRootNode, xmlio::Title))
592 SetTitle(fXML->GetAttr(fRootNode, xmlio::Title));
594 if (fXML->HasAttr(fRootNode, xmlio::IOVersion))
595 fIOVersion = fXML->GetIntAttr(fRootNode, xmlio::IOVersion);
599 if (fXML->HasAttr(fRootNode,
"file_version"))
600 fVersion = fXML->GetIntAttr(fRootNode,
"file_version");
602 fStreamerInfoNode = fXML->GetChild(fRootNode);
603 fXML->SkipEmpty(fStreamerInfoNode);
604 while (fStreamerInfoNode) {
605 if (strcmp(xmlio::SInfos, fXML->GetNodeName(fStreamerInfoNode)) == 0)
607 fXML->ShiftToNext(fStreamerInfoNode);
609 fXML->UnlinkNode(fStreamerInfoNode);
611 if (fStreamerInfoNode)
615 if (!fXML->ValidateDocument(fDoc, gDebug > 0)) {
621 ReadKeysList(
this, fRootNode);
623 fXML->CleanNode(fRootNode);
631 Int_t TXMLFile::ReadKeysList(TDirectory *dir, XMLNodePointer_t topnode)
633 if (!dir || !topnode)
638 XMLNodePointer_t keynode = fXML->GetChild(topnode);
639 fXML->SkipEmpty(keynode);
641 XMLNodePointer_t next = fXML->GetNext(keynode);
643 if (strcmp(xmlio::Xmlkey, fXML->GetNodeName(keynode)) == 0) {
644 fXML->UnlinkNode(keynode);
646 TKeyXML *key =
new TKeyXML(dir, ++fKeyCounter, keynode);
650 Info(
"ReadKeysList",
"Add key %s from node %s", key->GetName(), fXML->GetNodeName(keynode));
656 fXML->SkipEmpty(keynode);
665 void TXMLFile::WriteStreamerInfo()
667 if (fStreamerInfoNode) {
668 fXML->FreeNode(fStreamerInfoNode);
669 fStreamerInfoNode =
nullptr;
672 if (!IsStoreStreamerInfos())
677 TIter iter(gROOT->GetListOfStreamerInfo());
679 TStreamerInfo *info =
nullptr;
681 while ((info = (TStreamerInfo *)iter()) !=
nullptr) {
682 Int_t uid = info->GetNumber();
683 if (fClassIndex->fArray[uid])
687 if (list.GetSize() == 0)
690 fStreamerInfoNode = fXML->NewChild(
nullptr,
nullptr, xmlio::SInfos);
691 for (
int n = 0; n <= list.GetLast(); n++) {
692 info = (TStreamerInfo *)list.At(n);
694 XMLNodePointer_t infonode = fXML->NewChild(fStreamerInfoNode,
nullptr,
"TStreamerInfo");
696 fXML->NewAttr(infonode,
nullptr,
"name", info->GetName());
697 fXML->NewAttr(infonode,
nullptr,
"title", info->GetTitle());
699 fXML->NewIntAttr(infonode,
"v", info->IsA()->GetClassVersion());
700 fXML->NewIntAttr(infonode,
"classversion", info->GetClassVersion());
701 fXML->NewAttr(infonode,
nullptr,
"canoptimize",
702 (info->TestBit(TStreamerInfo::kCannotOptimize) ? xmlio::False : xmlio::True));
703 fXML->NewIntAttr(infonode,
"checksum", info->GetCheckSum());
705 TIter iter2(info->GetElements());
706 TStreamerElement *elem =
nullptr;
707 while ((elem = (TStreamerElement *)iter2()) !=
nullptr)
708 StoreStreamerElement(infonode, elem);
716 TFile::InfoListRet TXMLFile::GetStreamerInfoListImpl(
bool )
718 ROOT::Internal::RConcurrentHashColl::HashValue hash;
720 if (!fStreamerInfoNode)
721 return {
nullptr, 1, hash};
723 TList *list =
new TList();
725 XMLNodePointer_t sinfonode = fXML->GetChild(fStreamerInfoNode);
726 fXML->SkipEmpty(sinfonode);
729 if (strcmp(
"TStreamerInfo", fXML->GetNodeName(sinfonode)) == 0) {
730 TString fname = fXML->GetAttr(sinfonode,
"name");
731 TString ftitle = fXML->GetAttr(sinfonode,
"title");
733 TStreamerInfo *info =
new TStreamerInfo(TClass::GetClass(fname));
734 info->SetTitle(ftitle);
738 Int_t clversion = AtoI(fXML->GetAttr(sinfonode,
"classversion"));
739 info->SetClassVersion(clversion);
740 info->SetOnFileClassVersion(clversion);
741 Int_t checksum = AtoI(fXML->GetAttr(sinfonode,
"checksum"));
742 info->SetCheckSum(checksum);
744 const char *canoptimize = fXML->GetAttr(sinfonode,
"canoptimize");
745 if (!canoptimize || (strcmp(canoptimize, xmlio::False) == 0))
746 info->SetBit(TStreamerInfo::kCannotOptimize);
748 info->ResetBit(TStreamerInfo::kCannotOptimize);
750 XMLNodePointer_t node = fXML->GetChild(sinfonode);
751 fXML->SkipEmpty(node);
753 ReadStreamerElement(node, info);
754 fXML->ShiftToNext(node);
757 fXML->ShiftToNext(sinfonode);
762 return {list, 0, hash};
768 void TXMLFile::StoreStreamerElement(XMLNodePointer_t infonode, TStreamerElement *elem)
770 TClass *cl = elem->IsA();
772 XMLNodePointer_t node = fXML->NewChild(infonode,
nullptr, cl->GetName());
774 char sbuf[100], namebuf[100];
776 fXML->NewAttr(node,
nullptr,
"name", elem->GetName());
777 if (strlen(elem->GetTitle()) > 0)
778 fXML->NewAttr(node,
nullptr,
"title", elem->GetTitle());
780 fXML->NewIntAttr(node,
"v", cl->GetClassVersion());
782 fXML->NewIntAttr(node,
"type", elem->GetType());
784 if (strlen(elem->GetTypeName()) > 0)
785 fXML->NewAttr(node,
nullptr,
"typename", elem->GetTypeName());
787 fXML->NewIntAttr(node,
"size", elem->GetSize());
789 if (elem->GetArrayDim() > 0) {
790 fXML->NewIntAttr(node,
"numdim", elem->GetArrayDim());
792 for (
int ndim = 0; ndim < elem->GetArrayDim(); ndim++) {
793 sprintf(namebuf,
"dim%d", ndim);
794 fXML->NewIntAttr(node, namebuf, elem->GetMaxIndex(ndim));
798 if (cl == TStreamerBase::Class()) {
799 TStreamerBase *base = (TStreamerBase *)elem;
800 sprintf(sbuf,
"%d", base->GetBaseVersion());
801 fXML->NewAttr(node,
nullptr,
"baseversion", sbuf);
802 sprintf(sbuf,
"%d", base->GetBaseCheckSum());
803 fXML->NewAttr(node,
nullptr,
"basechecksum", sbuf);
804 }
else if (cl == TStreamerBasicPointer::Class()) {
805 TStreamerBasicPointer *bptr = (TStreamerBasicPointer *)elem;
806 fXML->NewIntAttr(node,
"countversion", bptr->GetCountVersion());
807 fXML->NewAttr(node,
nullptr,
"countname", bptr->GetCountName());
808 fXML->NewAttr(node,
nullptr,
"countclass", bptr->GetCountClass());
809 }
else if (cl == TStreamerLoop::Class()) {
810 TStreamerLoop *loop = (TStreamerLoop *)elem;
811 fXML->NewIntAttr(node,
"countversion", loop->GetCountVersion());
812 fXML->NewAttr(node,
nullptr,
"countname", loop->GetCountName());
813 fXML->NewAttr(node,
nullptr,
"countclass", loop->GetCountClass());
814 }
else if ((cl == TStreamerSTL::Class()) || (cl == TStreamerSTLstring::Class())) {
815 TStreamerSTL *stl = (TStreamerSTL *)elem;
816 fXML->NewIntAttr(node,
"STLtype", stl->GetSTLtype());
817 fXML->NewIntAttr(node,
"Ctype", stl->GetCtype());
824 void TXMLFile::ReadStreamerElement(XMLNodePointer_t node, TStreamerInfo *info)
826 TClass *cl = TClass::GetClass(fXML->GetNodeName(node));
827 if (!cl || !cl->InheritsFrom(TStreamerElement::Class()))
830 TStreamerElement *elem = (TStreamerElement *)cl->New();
832 int elem_type = fXML->GetIntAttr(node,
"type");
834 elem->SetName(fXML->GetAttr(node,
"name"));
835 elem->SetTitle(fXML->GetAttr(node,
"title"));
836 elem->SetType(elem_type);
837 elem->SetTypeName(fXML->GetAttr(node,
"typename"));
838 elem->SetSize(fXML->GetIntAttr(node,
"size"));
840 if (cl == TStreamerBase::Class()) {
841 int basever = fXML->GetIntAttr(node,
"baseversion");
842 ((TStreamerBase *)elem)->SetBaseVersion(basever);
843 Int_t baseCheckSum = fXML->GetIntAttr(node,
"basechecksum");
844 ((TStreamerBase *)elem)->SetBaseCheckSum(baseCheckSum);
845 }
else if (cl == TStreamerBasicPointer::Class()) {
846 TString countname = fXML->GetAttr(node,
"countname");
847 TString countclass = fXML->GetAttr(node,
"countclass");
848 Int_t countversion = fXML->GetIntAttr(node,
"countversion");
850 ((TStreamerBasicPointer *)elem)->SetCountVersion(countversion);
851 ((TStreamerBasicPointer *)elem)->SetCountName(countname);
852 ((TStreamerBasicPointer *)elem)->SetCountClass(countclass);
853 }
else if (cl == TStreamerLoop::Class()) {
854 TString countname = fXML->GetAttr(node,
"countname");
855 TString countclass = fXML->GetAttr(node,
"countclass");
856 Int_t countversion = fXML->GetIntAttr(node,
"countversion");
857 ((TStreamerLoop *)elem)->SetCountVersion(countversion);
858 ((TStreamerLoop *)elem)->SetCountName(countname);
859 ((TStreamerLoop *)elem)->SetCountClass(countclass);
860 }
else if ((cl == TStreamerSTL::Class()) || (cl == TStreamerSTLstring::Class())) {
861 int fSTLtype = fXML->GetIntAttr(node,
"STLtype");
862 int fCtype = fXML->GetIntAttr(node,
"Ctype");
863 ((TStreamerSTL *)elem)->SetSTLtype(fSTLtype);
864 ((TStreamerSTL *)elem)->SetCtype(fCtype);
869 if (fXML->HasAttr(node,
"numdim")) {
870 int numdim = fXML->GetIntAttr(node,
"numdim");
871 elem->SetArrayDim(numdim);
872 for (
int ndim = 0; ndim < numdim; ndim++) {
873 sprintf(namebuf,
"dim%d", ndim);
874 int maxi = fXML->GetIntAttr(node, namebuf);
875 elem->SetMaxIndex(ndim, maxi);
879 elem->SetType(elem_type);
880 elem->SetNewType(elem_type);
882 info->GetElements()->Add(elem);
910 void TXMLFile::SetXmlLayout(EXMLLayout layout)
912 if (IsWritable() && (GetListOfKeys()->GetSize() == 0))
913 TXMLSetup::SetXmlLayout(layout);
922 void TXMLFile::SetStoreStreamerInfos(Bool_t iConvert)
924 if (IsWritable() && (GetListOfKeys()->GetSize() == 0))
925 TXMLSetup::SetStoreStreamerInfos(iConvert);
933 void TXMLFile::SetUsedDtd(Bool_t use)
935 if (IsWritable() && (GetListOfKeys()->GetSize() == 0))
936 TXMLSetup::SetUsedDtd(use);
953 void TXMLFile::SetUseNamespaces(Bool_t iUseNamespaces)
955 if (IsWritable() && (GetListOfKeys()->GetSize() == 0))
956 TXMLSetup::SetUseNamespaces(iUseNamespaces);
964 Bool_t TXMLFile::AddXmlComment(
const char *comment)
969 return fXML->AddDocComment(fDoc, comment);
982 Bool_t TXMLFile::AddXmlStyleSheet(
const char *href,
const char *type,
const char *title,
int alternate,
983 const char *media,
const char *charset)
988 return fXML->AddDocStyleSheet(fDoc, href, type, title, alternate, media, charset);
998 Bool_t TXMLFile::AddXmlLine(
const char *line)
1003 return fXML->AddDocRawLine(fDoc, line);
1009 Long64_t TXMLFile::DirCreateEntry(TDirectory *dir)
1011 TDirectory *mother = dir->GetMotherDir();
1015 TKeyXML *key =
new TKeyXML(mother, ++fKeyCounter, dir, dir->GetName(), dir->GetTitle());
1019 return key->GetKeyId();
1025 TKeyXML *TXMLFile::FindDirKey(TDirectory *dir)
1027 TDirectory *motherdir = dir->GetMotherDir();
1031 TIter next(motherdir->GetListOfKeys());
1032 TObject *obj =
nullptr;
1034 while ((obj = next()) !=
nullptr) {
1035 TKeyXML *key =
dynamic_cast<TKeyXML *
>(obj);
1038 if (key->GetKeyId() == dir->GetSeekDir())
1048 TDirectory *TXMLFile::FindKeyDir(TDirectory *motherdir, Long64_t keyid)
1053 TIter next(motherdir->GetList());
1054 TObject *obj =
nullptr;
1056 while ((obj = next()) !=
nullptr) {
1057 TDirectory *dir =
dynamic_cast<TDirectory *
>(obj);
1059 if (dir->GetSeekDir() == keyid)
1070 Int_t TXMLFile::DirReadKeys(TDirectory *dir)
1072 TKeyXML *key = FindDirKey(dir);
1076 return ReadKeysList(dir, key->KeyNode());
1082 void TXMLFile::DirWriteKeys(TDirectory *)
1084 TIter next(GetListOfKeys());
1085 TObject *obj =
nullptr;
1087 while ((obj = next()) !=
nullptr) {
1088 TKeyXML *key =
dynamic_cast<TKeyXML *
>(obj);
1090 key->UpdateAttributes();
1097 void TXMLFile::DirWriteHeader(TDirectory *dir)
1099 TKeyXML *key = FindDirKey(dir);
1101 key->UpdateObject(dir);