Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TDirectoryFile.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Rene Brun 22/01/2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**
13 \class TDirectoryFile
14 \ingroup IO
15
16 A ROOT file is structured in Directories (like a file system).
17 Each Directory has a list of Keys (see TKeys) and a list of objects
18 in memory. A Key is a small object that describes the type and location
19 of a persistent object in a file. The persistent object may be a directory.
20Begin_Macro
21../../../tutorials/io/fildir.C
22End_Macro
23 The structure of a file is shown in TFile::TFile
24*/
25
26#include <iostream>
27#include "Strlen.h"
28#include "strlcpy.h"
29#include "TDirectoryFile.h"
30#include "TFile.h"
31#include "TBufferFile.h"
32#include "TBufferJSON.h"
33#include "TMapFile.h"
34#include "TClassTable.h"
35#include "TInterpreter.h"
36#include "THashList.h"
37#include "TBrowser.h"
38#include "TFree.h"
39#include "TKey.h"
40#include "TStreamerInfo.h"
41#include "TROOT.h"
42#include "TError.h"
43#include "Bytes.h"
44#include "TClass.h"
45#include "TRegexp.h"
46#include "TSystem.h"
47#include "TStreamerElement.h"
48#include "TProcessUUID.h"
49#include "TVirtualMutex.h"
52const UInt_t kIsBigFile = BIT(16);
53const Int_t kMaxLen = 2048;
54
56
57
58////////////////////////////////////////////////////////////////////////////////
59/// Default TDirectoryFile constructor
62{
63 /// Intentionally placed here
64 /// when TDirectoryFile() = default; used, mac1014/cxx17 fails on some tests
65 /// Problem with TObject::IsOnHeap() failing
66}
67
68
69////////////////////////////////////////////////////////////////////////////////
70/// Create a new TDirectoryFile
71///
72/// A new directory with a name and a title is created in the current directory.
73/// The directory header information is immediately saved on the file
74/// A new key is added in the parent directory.
75/// When this constructor is called from a class directly derived
76/// from TDirectoryFile, the third argument, classname, MUST be specified.
77/// In this case, classname must be the name of the derived class.
78///
79/// Note that the directory name cannot contain slashes.
81TDirectoryFile::TDirectoryFile(const char *name, const char *title, Option_t *classname, TDirectory* initMotherDir)
82{
83 // We must not publish this objects to the list of RecursiveRemove (indirectly done
84 // by 'Appending' this object to it's mother) before the object is completely
85 // initialized.
86 // However a better option would be to delay the publishing until the very end,
87 // but it is currently done in the middle of the initialization (by Build which
88 // is a public interface) ....
90
91 fName = name;
92 fTitle = title;
93
94 if (!initMotherDir) initMotherDir = gDirectory;
95
96 if (strchr(name,'/')) {
97 ::Error("TDirectoryFile","directory name (%s) cannot contain a slash", name);
98 gDirectory = nullptr;
99 return;
100 }
101 if (strlen(GetName()) == 0) {
102 ::Error("TDirectoryFile","directory name cannot be \"\"");
103 gDirectory = nullptr;
104 return;
105 }
106
107 BuildDirectoryFile(initMotherDir ? initMotherDir->GetFile() : nullptr, initMotherDir);
108
109 TDirectory* motherdir = GetMotherDir();
111
112 if (!motherdir || !f) return;
113 if (!f->IsWritable()) return; //*-* in case of a directory in memory
114 if (motherdir->GetKey(name)) {
115 Error("TDirectoryFile","An object with name %s exists already", name);
116 return;
117 }
118 TClass *cl = nullptr;
119 if (classname[0]) {
120 cl = TClass::GetClass(classname);
121 if (!cl) {
122 Error("TDirectoryFile","Invalid class name: %s",classname);
123 return;
124 }
125 } else {
126 cl = TDirectoryFile::IsA();
127 }
128
129 fBufferSize = 0;
131
133
135
136 // Temporarily redundant, see comment on lock early in the function.
137 // R__LOCKGUARD(gROOTMutex);
138 gROOT->GetUUIDs()->AddUUID(fUUID,this);
139 // We should really be doing this now rather than in Build, see
140 // comment at the start of the function.
141 // if (initMotherDir && strlen(GetName()) != 0) initMotherDir->Append(this);
142}
143
144////////////////////////////////////////////////////////////////////////////////
145/// Initialize the key associated with this directory (and the related
146/// data members.
149{
150 TFile* f = GetFile(); // NOLINT: silence clang-tidy warnings
151 if (f->IsBinary()) {
152 if (!cl) {
153 cl = IsA(); // NOLINT: silence clang-tidy warnings
154 }
155 TDirectory* motherdir = GetMotherDir();
156 fSeekParent = f->GetSeekDir();
157 Int_t nbytes = TDirectoryFile::Sizeof();
158 TKey *key = new TKey(fName,fTitle,cl,nbytes,motherdir);
159 fNbytesName = key->GetKeylen();
160 fSeekDir = key->GetSeekKey();
161 if (fSeekDir == 0) return;
162 char *buffer = key->GetBuffer();
164 Int_t cycle = motherdir ? motherdir->AppendKey(key) : 0;
165 key->WriteFile(cycle);
166 } else {
167 fSeekParent = 0;
168 fNbytesName = 0;
169 fSeekDir = f->DirCreateEntry(this);
170 if (fSeekDir == 0) return;
171 }
172
173}
174
175////////////////////////////////////////////////////////////////////////////////
176/// Destructor.
179{
180 if (fKeys) {
181 fKeys->Delete("slow");
183 }
184
186
187 // Delete our content before we become somewhat invalid
188 // since some those objects (TTree for example) needs information
189 // from this object. Note that on some platform after the end
190 // of the body (i.e. thus during ~TDirectory which is also
191 // contains this code) the execution of 'this->GetFile()' fails
192 // to return the 'proper' value (because it uses the wrong
193 // virtual function).
194 if (fList) {
195 fList->Delete("slow");
197 }
198
199 if (gDebug) {
200 Info("~TDirectoryFile", "dtor called for %s", GetName());
201 }
202}
203
204////////////////////////////////////////////////////////////////////////////////
205/// Append object to this directory.
206///
207/// If replace is true:
208/// remove any existing objects with the same same (if the name is not ""
210void TDirectoryFile::Append(TObject *obj, Bool_t replace /* = kFALSE */)
211{
212 if (!obj || !fList) return;
213
214 TDirectory::Append(obj,replace);
215
216 if (!fMother) return;
217 if (fMother->IsA() == TMapFile::Class()) {
218 TMapFile *mfile = (TMapFile*)fMother;
219 mfile->Add(obj);
220 }
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// Insert key in the linked list of keys of this directory.
227{
228 if (!fKeys) {
229 Error("AppendKey","TDirectoryFile not initialized yet.");
230 return 0;
231 }
232
234
235 key->SetMotherDir(this);
236
237 // This is a fast hash lookup in case the key does not already exist
238 TKey *oldkey = (TKey*)fKeys->FindObject(key->GetName());
239 if (!oldkey) {
240 fKeys->Add(key);
241 return 1;
242 }
243
244 // If the key name already exists we have to make a scan for it
245 // and insert the new key ahead of the current one
246 TObjLink *lnk = fKeys->FirstLink();
247 while (lnk) {
248 oldkey = (TKey*)lnk->GetObject();
249 if (!strcmp(oldkey->GetName(), key->GetName()))
250 break;
251 lnk = lnk->Next();
252 }
253
254 fKeys->AddBefore(lnk, key);
255 return oldkey->GetCycle() + 1;
256}
257
258////////////////////////////////////////////////////////////////////////////////
259/// Browse the content of the directory.
262{
264
265 if (b) {
266 TObject *obj = nullptr;
267 TIter nextin(fList);
268 TKey *key = nullptr, *keyo = nullptr;
269 TIter next(fKeys);
270
271 cd();
272
273 //Add objects that are only in memory
274 while ((obj = nextin())) {
275 if (fKeys->FindObject(obj->GetName())) continue;
276 b->Add(obj, obj->GetName());
277 }
278
279 //Add keys
280 while ((key = (TKey *) next())) {
281 int skip = 0;
282 if (!keyo || (keyo && strcmp(keyo->GetName(), key->GetName()))) {
283 skip = 0;
284 obj = fList->FindObject(key->GetName());
285
286 if (obj) {
287 b->Add(obj, obj->GetName());
288 if (obj->IsFolder() && !obj->InheritsFrom("TTree"))
289 skip = 1;
290 }
291 }
292
293 if (!skip) {
294 name.Form("%s;%d", key->GetName(), key->GetCycle());
295 b->Add(key, name);
296 }
297
298 keyo = key;
299 }
300 }
301}
302
303////////////////////////////////////////////////////////////////////////////////
304/// Initialise directory to defaults.
306void TDirectoryFile::BuildDirectoryFile(TFile* motherFile, TDirectory* motherDir)
307{
308 // If directory is created via default ctor (when dir is read from file)
309 // don't add it here to the directory since its name is not yet known.
310 // It will be added to the directory in TKey::ReadObj().
311
312 if (motherDir && strlen(GetName()) != 0) motherDir->Append(this);
313
316 fDatimeC.Set();
317 fDatimeM.Set();
318 fNbytesKeys = 0;
319 fSeekDir = 0;
320 fSeekParent = 0;
321 fSeekKeys = 0;
322 fList = new THashList(100,50);
323 fKeys = new THashList(100,50);
324 fList->UseRWLock();
325 fMother = motherDir;
326 fFile = motherFile ? motherFile : TFile::CurrentFile();
328}
329
330////////////////////////////////////////////////////////////////////////////////
331/// Change current directory to "this" directory.
332///
333/// Returns kTRUE in case of success.
336{
337 Bool_t ok = TDirectory::cd();
338 if (ok)
340 return ok;
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Change current directory the directory described by the path if given one.
345/// change the current directory to "path". The absolute path syntax is:
346///
347/// file.root:/dir1/dir2
348///
349/// where file.root is the file and /dir1/dir2 the desired subdirectory
350/// in the file. Relative syntax is relative to "this" directory. E.g:
351/// ../aa. Returns kTRUE in case of success.
353Bool_t TDirectoryFile::cd(const char *path)
354{
355 Bool_t ok = TDirectory::cd(path);
356 if (ok)
358 return ok;
359}
360
361////////////////////////////////////////////////////////////////////////////////
362/// Clean the pointers to this object (gDirectory, TContext, etc.)
365{
366 // After CleanTargets either gFile was changed appropriately
367 // by a cd() or needs to be set to zero.
368 if (gFile == this) {
369 gFile = nullptr;
370 }
371
373}
374
375////////////////////////////////////////////////////////////////////////////////
376/// Make a clone of an object using the Streamer facility.
377///
378/// If the object derives from TNamed, this function is called
379/// by TNamed::Clone. TNamed::Clone uses the optional argument newname to set
380/// a new name to the newly created object.
381///
382/// If autoadd is true and if the object class has a
383/// DirectoryAutoAdd function, it will be called at the end of the
384/// function with the parameter gDirectory. This usually means that
385/// the object will be appended to the current ROOT directory.
387TObject *TDirectoryFile::CloneObject(const TObject *obj, Bool_t autoadd /* = kTRUE */)
388{
389 // if no default ctor return immediately (error issued by New())
390 char *pobj = (char*)obj->IsA()->New();
391 if (!pobj) return nullptr;
392
393 Int_t baseOffset = obj->IsA()->GetBaseClassOffset(TObject::Class());
394 if (baseOffset==-1) {
395 // cl does not inherit from TObject.
396 // Since this is not supported in this function, the only reason we could reach this code
397 // is because something is screwed up in the ROOT code.
398 Fatal("CloneObject","Incorrect detection of the inheritance from TObject for class %s.\n",
399 obj->IsA()->GetName());
400 }
401 TObject *newobj = (TObject*)(pobj+baseOffset);
402
403 //create a buffer where the object will be streamed
404 {
405 // NOTE: do we still need to make this change to gFile?
406 // NOTE: This can not be 'gDirectory=0' as at least roofit expect gDirectory to not be null
407 // during the streaming ....
408 TFile *filsav = gFile;
409 gFile = nullptr;
410 const Int_t bufsize = 10000;
411 TBufferFile buffer(TBuffer::kWrite,bufsize);
412 buffer.MapObject(obj); //register obj in map to handle self reference
413 {
414 Bool_t isRef = obj->TestBit(kIsReferenced);
415 ((TObject*)obj)->ResetBit(kIsReferenced);
416
417 ((TObject*)obj)->Streamer(buffer);
418
419 if (isRef) ((TObject*)obj)->SetBit(kIsReferenced);
420 }
421
422 // read new object from buffer
423 buffer.SetReadMode();
424 buffer.ResetMap();
425 buffer.SetBufferOffset(0);
426 buffer.MapObject(newobj); //register obj in map to handle self reference
427 newobj->Streamer(buffer);
428 newobj->ResetBit(kIsReferenced);
429 newobj->ResetBit(kCanDelete);
430 gFile = filsav;
431 }
432
433 if (autoadd) {
435 if (func) {
436 func(newobj,this);
437 }
438 }
439 return newobj;
440}
441
442////////////////////////////////////////////////////////////////////////////////
443/// Scan the memory lists of all files for an object with name
446{
447 TFile *f;
449 TIter next(gROOT->GetListOfFiles());
450 while ((f = (TFile*)next())) {
451 TObject *obj = f->GetList()->FindObject(name);
452 if (obj) return obj;
453 }
454 return nullptr;
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// Find a directory named "apath".
459///
460/// It apath is null or empty, returns "this" directory.
461/// Otherwise use the name "apath" to find a directory.
462/// The absolute path syntax is:
463///
464/// file.root:/dir1/dir2
465///
466/// where file.root is the file and /dir1/dir2 the desired subdirectory
467/// in the file. Relative syntax is relative to "this" directory. E.g:
468/// ../aa.
469/// Returns 0 in case path does not exist.
470/// If printError is true, use Error with 'funcname' to issue an error message.
473 Bool_t printError, const char *funcname)
474{
475 Int_t nch = 0;
476 if (apath) nch = strlen(apath);
477 if (!nch) {
478 return this;
479 }
480
481 if (funcname==0 || strlen(funcname)==0) funcname = "GetDirectory";
482
483 TDirectory *result = this;
484
485 char *path = new char[nch+1]; path[0] = 0;
486 if (nch) strlcpy(path,apath,nch+1);
487 char *s = (char*)strchr(path, ':');
488 if (s) {
489 *s = '\0';
491 TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path);
492 // Check if this is a duplicate (2nd opening) on this file and prefer
493 // this file.
494 if (GetFile()) {
495 auto url = GetFile()->GetEndpointUrl();
496 if (f && 0 == url->Compare(f->GetFile()->GetEndpointUrl())) {
497 result = GetDirectory(s+1,printError,funcname);
498 delete [] path;
499 return result;
500 }
501 }
502 if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT;
503 if (s) *s = ':';
504 if (f) {
505 result = f;
506 if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname);
507 delete [] path; return result;
508 } else {
509 if (printError) Error(funcname, "No such file %s", path);
510 delete [] path; return nullptr;
511 }
512 }
513
514 // path starts with a slash (assumes current file)
515 if (path[0] == '/') {
516 TDirectory *td = fFile;
517 if (!fFile) td = gROOT;
518 result = td->GetDirectory(path+1,printError,funcname);
519 delete [] path; return result;
520 }
521
522 TDirectoryFile *obj;
523 char *slash = (char*)strchr(path,'/');
524 if (!slash) { // we are at the lowest level
525 if (!strcmp(path, "..")) {
527 delete [] path; return result;
528 }
529 GetObject(path,obj);
530 if (!obj) {
531 if (printError) Error(funcname,"Unknown directory %s", path);
532 delete [] path; return nullptr;
533 }
534
535 delete [] path; return obj;
536 }
537
538 TString subdir(path);
539 slash = (char*)strchr(subdir.Data(),'/');
540 *slash = 0;
541 //Get object with path from current directory/file
542 if (!strcmp(subdir, "..")) {
543 TDirectory* mom = GetMotherDir();
544 if (mom)
545 result = mom->GetDirectory(slash+1,printError,funcname);
546 delete [] path; return result;
547 }
548 GetObject(subdir,obj);
549 if (!obj) {
550 if (printError) Error(funcname,"Unknown directory %s", subdir.Data());
551 delete [] path; return nullptr;
552 }
553
554 result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname);
555 delete [] path; return result;
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Delete all objects from memory and directory structure itself.
562{
563 if (!fList || !fSeekDir) {
564 return;
565 }
566
567 // Save the directory key list and header
568 Save();
569
570 Bool_t nodelete = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE;
571
572 if (!nodelete) {
573 Bool_t fast = kTRUE;
574 TObjLink *lnk = fList->FirstLink();
575 while (lnk) {
576 if (lnk->GetObject()->IsA() == TDirectoryFile::Class()) {fast = kFALSE;break;}
577 lnk = lnk->Next();
578 }
579 // Delete objects from directory list, this in turn, recursively closes all
580 // sub-directories (that were allocated on the heap)
581 // if this dir contains subdirs, we must use the slow option for Delete!
582 // we must avoid "slow" as much as possible, in particular Delete("slow")
583 // with a large number of objects (eg >10^5) would take for ever.
584 {
585 if (fast) fList->Delete();
586 else fList->Delete("slow");
587 }
588 }
589
590 // Delete keys from key list (but don't delete the list header)
591 if (fKeys) {
592 fKeys->Delete("slow");
593 }
594
596}
597
598////////////////////////////////////////////////////////////////////////////////
599/// Delete Objects or/and keys in a directory
600///
601/// Properties of the namecycle string:
602/// - namecycle has the format name;cycle
603/// - namecycle = "" is same as namecycle ="T*"
604/// - name = * means all
605/// - cycle = * means all cycles (memory and keys)
606/// - cycle = "" or cycle = 9999 ==> apply to a memory object
607/// When name=* use T* to delete subdirectories also
608///
609/// To delete one directory, you must specify the directory cycle,
610/// eg. file.Delete("dir1;1");
611///
612/// Examples:
613/// | Pattern | Description |
614/// |---------|-------------|
615/// | foo | delete object named foo in memory |
616/// | foo* | delete all objects with a name starting with foo |
617/// | foo;1 | delete cycle 1 of foo on file |
618/// | foo;* | delete all cycles of foo on file and also from memory |
619/// | *;2 | delete all objects on file having the cycle 2 |
620/// | *;* | delete all objects from memory and file |
621/// | T*;* | delete all objects from memory and file and all subdirectories |
622///
623/// ## WARNING
624/// If the key to be deleted contains special characters ("+","^","?", etc
625/// that have a special meaning for the regular expression parser (see TRegexp)
626/// then you must specify 2 backslash characters to escape the regular expression.
627/// For example, if the key to be deleted is namecycle = "C++", you must call
628///
629/// mydir.Delete("C\\+\\+"));
630///
632void TDirectoryFile::Delete(const char *namecycle)
633{
634 if (gDebug)
635 Info("Delete","Call for this = %s namecycle = %s",
636 GetName(), (namecycle ? namecycle : "null"));
637
638 TDirectory::TContext ctxt(this);
639 Short_t cycle;
640 char name[kMaxLen];
641 const char *nmcy = (namecycle) ? namecycle : "";
642 DecodeNameCycle(nmcy, name, cycle, kMaxLen);
643
644 Int_t deleteall = 0;
645 Int_t deletetree = 0;
646 if(strcmp(name,"*") == 0) deleteall = 1;
647 if(strcmp(name,"*T") == 0){ deleteall = 1; deletetree = 1;}
648 if(strcmp(name,"T*") == 0){ deleteall = 1; deletetree = 1;}
649 if(namecycle==0 || !namecycle[0]){ deleteall = 1; deletetree = 1;}
650 TRegexp re(name,kTRUE);
651 TString s;
652 Int_t deleteOK = 0;
653
654//*-*---------------------Case of Object in memory---------------------
655// ========================
656 if (cycle >= 9999 ) {
657 TNamed *idcur;
658 TIter next(fList);
659 while ((idcur = (TNamed *) next())) {
660 deleteOK = 0;
661 s = idcur->GetName();
662 if (deleteall || s.Index(re) != kNPOS) {
663 deleteOK = 1;
664 if (idcur->IsA() == TDirectoryFile::Class()) {
665 deleteOK = 2;
666 if (!deletetree && deleteall) deleteOK = 0;
667 }
668 }
669 if (deleteOK != 0) {
670 fList->Remove(idcur);
671 if (deleteOK==2) {
672 // read subdirectories to correctly delete them
673 if (deletetree)
674 ((TDirectory*) idcur)->ReadAll("dirs");
675 idcur->Delete(deletetree ? "T*;*" : "*");
676 delete idcur;
677 } else
678 idcur->Delete(name);
679 }
680 }
681// if (deleteOK == 2) {
682// Info("Delete","Dir:%lx %s", fList->FindObject(name), name);
683// delete fList->FindObject(name); //deleting a TDirectory
684// }
685 }
686//*-*---------------------Case of Key---------------------
687// ===========
688 if (cycle != 9999 ) {
689 if (IsWritable()) {
690 TKey *key;
691 TIter nextkey(GetListOfKeys());
692 while ((key = (TKey *) nextkey())) {
693 deleteOK = 0;
694 s = key->GetName();
695 if (deleteall || s.Index(re) != kNPOS) {
696 if (cycle == key->GetCycle()) deleteOK = 1;
697 if (cycle > 9999) deleteOK = 1;
698 //if (!strcmp(key->GetClassName(),"TDirectory")) {
699 if (strstr(key->GetClassName(),"TDirectory")) {
700 deleteOK = 2;
701 if (!deletetree && deleteall) deleteOK = 0;
702 if (cycle == key->GetCycle()) deleteOK = 2;
703 }
704 }
705 if (deleteOK) {
706 if (deleteOK==2) {
707 // read directory with subdirectories to correctly delete and free key structure
708 TDirectory* dir = GetDirectory(key->GetName(), kTRUE, "Delete");
709 if (dir!=0) {
710 dir->Delete("T*;*");
711 fList->Remove(dir);
712 delete dir;
713 }
714 }
715
716 key->Delete();
717 fKeys->Remove(key);
719 delete key;
720 }
721 }
722 TFile* f = GetFile();
723 if (fModified && (f!=0)) {
724 WriteKeys(); //*-* Write new keys structure
725 WriteDirHeader(); //*-* Write new directory header
726 f->WriteFree(); //*-* Write new free segments list
727 f->WriteHeader(); //*-* Write new file header
728 }
729 }
730 }
731}
732
733////////////////////////////////////////////////////////////////////////////////
734/// Encode directory header into output buffer
736void TDirectoryFile::FillBuffer(char *&buffer)
737{
742 {
743 // One of the address is larger than 2GB we need to use longer onfile
744 // integer, thus we increase the version number.
745 // Note that fSeekDir and fSeekKey are not necessarily correlated, if
746 // some object are 'removed' from the file and the holes are reused.
747 version += 1000;
748 }
749 tobuf(buffer, version);
750 const bool reproducible = TestBit(TFile::kReproducible) || (fFile && fFile->TestBit(TFile::kReproducible));
751 if (reproducible) {
752 TDatime((UInt_t) 1).FillBuffer(buffer);
753 TDatime((UInt_t) 1).FillBuffer(buffer);
754 } else {
755 fDatimeC.FillBuffer(buffer);
756 fDatimeM.FillBuffer(buffer);
757 }
758 tobuf(buffer, fNbytesKeys);
759 tobuf(buffer, fNbytesName);
760 if (version > 1000) {
761 tobuf(buffer, fSeekDir);
762 tobuf(buffer, fSeekParent);
763 tobuf(buffer, fSeekKeys);
764 } else {
765 tobuf(buffer, (Int_t)fSeekDir);
766 tobuf(buffer, (Int_t)fSeekParent);
767 tobuf(buffer, (Int_t)fSeekKeys);
768 }
769 if (reproducible)
770 TUUID("00000000-0000-0000-0000-000000000000").FillBuffer(buffer);
771 else
772 fUUID.FillBuffer(buffer);
773 if (fFile && fFile->GetVersion() < 40000) return;
774 if (version <=1000) for (Int_t i=0;i<3;i++) tobuf(buffer,Int_t(0));
775}
776
777////////////////////////////////////////////////////////////////////////////////
778/// Find key with name keyname in the current directory
780TKey *TDirectoryFile::FindKey(const char *keyname) const
781{
782 Short_t cycle;
783 char name[kMaxLen];
784
785 DecodeNameCycle(keyname, name, cycle, kMaxLen);
786 return GetKey(name,cycle);
787}
788
789////////////////////////////////////////////////////////////////////////////////
790/// Find key with name keyname in the current directory or
791/// its subdirectories.
792///
793/// NOTE: that If a key is found, the directory containing the key becomes
794/// the current directory
796TKey *TDirectoryFile::FindKeyAny(const char *keyname) const
797{
798 TDirectory *dirsav = gDirectory;
799 Short_t cycle;
800 char name[kMaxLen];
801
802 DecodeNameCycle(keyname, name, cycle, kMaxLen);
803
804 auto listOfKeys = dynamic_cast<THashList *>(GetListOfKeys());
805 if (!listOfKeys) {
806 Error("FindKeyAny", "Unexpected type of TDirectoryFile::fKeys!");
807 return nullptr;
808 }
809
810 if (const TList *keyList = listOfKeys->GetListForObject(name)) {
811 for (auto key: TRangeDynCast<TKey>(*keyList)) {
812 if (key && !strcmp(key->GetName(), name)
813 && (cycle == 9999 || cycle >= key->GetCycle())) {
814 const_cast<TDirectoryFile*>(this)->cd(); // may be we should not make cd ???
815 return key;
816 }
817 }
818 }
819
820 //try with subdirectories
821 TIter next(GetListOfKeys());
822 TKey *key;
823 while ((key = (TKey *) next())) {
824 //if (!strcmp(key->GetClassName(),"TDirectory")) {
825 if (strstr(key->GetClassName(),"TDirectory")) {
826 TDirectory* subdir =
827 const_cast<TDirectoryFile*>(this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny");
828 TKey *k = subdir ? subdir->FindKeyAny(keyname) : nullptr;
829 if (k) return k;
830 }
831 }
832 if (dirsav) dirsav->cd();
833 return nullptr;
834}
835
836////////////////////////////////////////////////////////////////////////////////
837/// Find object by name in the list of memory objects of the current
838/// directory or its sub-directories.
839///
840/// After this call the current directory is not changed.
841/// To automatically set the current directory where the object is found,
842/// use FindKeyAny(aname)->ReadObj().
844TObject *TDirectoryFile::FindObjectAny(const char *aname) const
845{
846 //object may be already in the list of objects in memory
848 if (obj) return obj;
849
850 TDirectory *dirsav = gDirectory;
851 Short_t cycle;
852 char name[kMaxLen];
853
854 DecodeNameCycle(aname, name, cycle, kMaxLen);
855
856 auto listOfKeys = dynamic_cast<THashList *>(GetListOfKeys());
857 if (!listOfKeys) {
858 Error("FindObjectAny", "Unexpected type of TDirectoryFile::fKeys!");
859 return nullptr;
860 }
861
862 if (const TList *keyList = listOfKeys->GetListForObject(name)) {
863 for (auto key: TRangeDynCast<TKey>(*keyList)) {
864 if (key && !strcmp(key->GetName(), name)
865 && (cycle == 9999 || cycle >= key->GetCycle())) {
866 return key->ReadObj();
867 }
868 }
869 }
870
871 //try with subdirectories
872 TIter next(GetListOfKeys());
873 TKey *key;
874 while ((key = (TKey *) next())) {
875 //if (!strcmp(key->GetClassName(),"TDirectory")) {
876 if (strstr(key->GetClassName(),"TDirectory")) {
877 TDirectory* subdir =
878 ((TDirectory*)this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny");
879 TKey *k = subdir ? subdir->FindKeyAny(aname) : nullptr;
880 if (k) { if (dirsav) dirsav->cd(); return k->ReadObj();}
881 }
882 }
883 if (dirsav) dirsav->cd();
884 return nullptr;
885}
886
887////////////////////////////////////////////////////////////////////////////////
888/// Return pointer to object identified by namecycle.
889///
890/// Properties:
891/// - namecycle has the format name;cycle
892/// - name = * is illegal, cycle = * is illegal
893/// - cycle = "" or cycle = 9999 ==> apply to a memory object
894///
895/// Examples:
896/// | %Pattern | Explanation |
897/// |----------|-------------|
898/// | foo | get object named foo in memory if object is not in memory, try with highest cycle from file |
899/// | foo;1 | get cycle 1 of foo on file |
900///
901/// The retrieved object should in principle derive from TObject.
902/// If not, the function TDirectoryFile::Get<T> should be called.
903/// However, this function will still work for a non-TObject, provided that
904/// the calling application cast the return type to the correct type (which
905/// is the actual type of the object).
906///
907/// ### The Get<T> Method
908/// The method Get<T> offers better protection and avoids the need for any
909/// cast:
910/// ~~~{.cpp}
911/// auto objPtr = directory->Get<MyClass>("some object");
912/// if (objPtr) { ... the object exist and inherits from MyClass ... }
913/// ~~~
914///
915/// ### Very important note about inheritance
916/// In case the class of this object derives from TObject but not
917/// as a first inheritance, one must use dynamic_cast<>().
918///
919/// #### Example 1 - Normal case:
920///
921/// class MyClass : public TObject, public AnotherClass
922///
923/// then on return, one can adopt a C style cast:
924///
925/// auto objPtr = (MyClass*)directory->Get("some object of MyClass");
926///
927/// #### Example 2 - Special case:
928///
929/// class MyClass : public AnotherClass, public TObject
930///
931/// then on return, one must do:
932///
933/// auto objPtr = dynamic_cast<MyClass*>(directory->Get("some object of MyClass"));
934///
935/// Of course, dynamic_cast<> can also be used in the example 1.
936///
938TObject *TDirectoryFile::Get(const char *namecycle)
939{
940 Short_t cycle;
941 char name[kMaxLen];
942
943 DecodeNameCycle(namecycle, name, cycle, kMaxLen);
944 Int_t nch = strlen(name);
945 for (Int_t i = nch-1; i > 0; i--) {
946 if (name[i] == '/') {
947 name[i] = 0;
948 TDirectory* dirToSearch=GetDirectory(name);
949 const char *subnamecycle = namecycle + i + 1;
950 name[i] = '/';
951 return dirToSearch?dirToSearch->Get(subnamecycle):0;
952 }
953 }
954 const char *namobj = name;
955
956//*-*---------------------Case of Object in memory---------------------
957// ========================
958 TObject *idcur = fList ? fList->FindObject(namobj) : nullptr;
959 if (idcur) {
960 if (idcur==this && strlen(namobj)!=0) {
961 // The object has the same name has the directory and
962 // that's what we picked-up! We just need to ignore
963 // it ...
964 idcur = nullptr;
965 } else if (cycle == 9999) {
966 return idcur;
967 } else {
968 if (idcur->InheritsFrom(TCollection::Class()))
969 idcur->Delete(); // delete also list elements
970 delete idcur;
971 idcur = nullptr;
972 }
973 }
974
975//*-*---------------------Case of Key---------------------
976// ===========
977 auto listOfKeys = dynamic_cast<THashList *>(GetListOfKeys());
978 if (!listOfKeys) {
979 Error("Get", "Unexpected type of TDirectoryFile::fKeys!");
980 return nullptr;
981 }
982
983 if (const TList *keyList = listOfKeys->GetListForObject(namobj)) {
984 for (auto key: TRangeDynCast<TKey>(*keyList)) {
985 if (key && !strcmp(key->GetName(), namobj)
986 && (cycle == 9999 || cycle == key->GetCycle())) {
987 TDirectory::TContext ctxt(this);
988 return key->ReadObj();
989 }
990 }
991 }
992
993 return nullptr;
994}
995
996////////////////////////////////////////////////////////////////////////////////
997/// Return pointer to object identified by namecycle.
998///
999/// The returned object may or may not derive from TObject.
1000///
1001/// - namecycle has the format name;cycle
1002/// - name = * is illegal, cycle = * is illegal
1003/// - cycle = "" or cycle = 9999 ==> apply to a memory object
1004///
1005/// ## Very important note
1006/// The calling application must cast the returned object to
1007/// the final type, e.g.
1008///
1009/// auto objPtr = (MyClass*)directory->GetObject("some object of MyClass");
1011void *TDirectoryFile::GetObjectUnchecked(const char *namecycle)
1012{
1013 return GetObjectChecked(namecycle,(TClass*)nullptr);
1014}
1015
1016////////////////////////////////////////////////////////////////////////////////
1017/// See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl)
1019void *TDirectoryFile::GetObjectChecked(const char *namecycle, const char* classname)
1020{
1021 return GetObjectChecked(namecycle,TClass::GetClass(classname));
1022}
1023
1024
1025////////////////////////////////////////////////////////////////////////////////
1026/// Return pointer to object identified by namecycle if and only if the actual
1027/// object is a type suitable to be stored as a pointer to a "expectedClass"
1028/// If expectedClass is null, no check is performed.
1029///
1030/// - namecycle has the format name;cycle
1031/// - name = * is illegal, cycle = * is illegal
1032/// - cycle = "" or cycle = 9999 ==> apply to a memory object
1033///
1034/// ### Very important note
1035/// The calling application must cast the returned pointer to
1036/// the type described by the 2 arguments (i.e. cl):
1037///
1038/// auto objPtr = (MyClass*)directory->GetObjectChecked("some object of MyClass","MyClass"));
1039///
1040/// Note: We recommend using the method TDirectoryFile::Get<T>:
1041/// ~~~{.cpp}
1042/// auto objPtr = directory->Get<MyClass>("some object inheriting from MyClass");
1043/// if (objPtr) { ... we found what we are looking for ... }
1044/// ~~~
1046void *TDirectoryFile::GetObjectChecked(const char *namecycle, const TClass* expectedClass)
1047{
1048
1049 // If the name is invalid, issue an error message and return a nullptr
1050 if (!namecycle || '\0' == namecycle[0]) {
1051 Error("GetObjectChecked", "The provided key name is invalid.");
1052 return nullptr;
1053 }
1054
1055 Short_t cycle;
1056 char name[kMaxLen];
1057
1058 DecodeNameCycle(namecycle, name, cycle, kMaxLen);
1059 Int_t nch = strlen(name);
1060 for (Int_t i = nch-1; i > 0; i--) {
1061 if (name[i] == '/') {
1062 name[i] = 0;
1063 TDirectory* dirToSearch=GetDirectory(name);
1064 const char *subnamecycle = namecycle + i + 1;
1065 name[i] = '/';
1066 if (dirToSearch) {
1067 return dirToSearch->GetObjectChecked(subnamecycle, expectedClass);
1068 } else {
1069 return nullptr;
1070 }
1071 }
1072 }
1073 const char *namobj = name;
1074
1075//*-*---------------------Case of Object in memory---------------------
1076// ========================
1077 if (expectedClass==0 || expectedClass->IsTObject()) {
1078 TObject *objcur = fList ? fList->FindObject(namobj) : nullptr;
1079 if (objcur) {
1080 if (objcur==this && strlen(namobj)!=0) {
1081 // The object has the same name has the directory and
1082 // that's what we picked-up! We just need to ignore
1083 // it ...
1084 objcur = nullptr;
1085 } else if (cycle == 9999) {
1086 // Check type
1087 if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return nullptr;
1088 else return objcur;
1089 } else {
1090 if (objcur->InheritsFrom(TCollection::Class()))
1091 objcur->Delete(); // delete also list elements
1092 delete objcur;
1093 objcur = nullptr;
1094 }
1095 }
1096 }
1097
1098//*-*---------------------Case of Key---------------------
1099// ===========
1100 auto listOfKeys = dynamic_cast<THashList *>(GetListOfKeys());
1101 if (!listOfKeys) {
1102 Error("GetObjectChecked", "Unexpected type of TDirectoryFile::fKeys!");
1103 return nullptr;
1104 }
1105
1106 if (const TList *keyList = listOfKeys->GetListForObject(namobj)) {
1107 for (auto key: TRangeDynCast<TKey>(*keyList)) {
1108 if (key && !strcmp(key->GetName(), namobj)
1109 && (cycle == 9999 || cycle == key->GetCycle())) {
1110 TDirectory::TContext ctxt(this);
1111 return key->ReadObjectAny(expectedClass);
1112 }
1113 }
1114 }
1115
1116 return nullptr;
1117}
1118
1119////////////////////////////////////////////////////////////////////////////////
1120/// Return the buffer size to create new TKeys.
1121///
1122/// If the stored fBufferSize is null, the value returned is the average
1123/// buffer size of objects in the file so far.
1126{
1127 if (fBufferSize <= 0) return fFile->GetBestBuffer();
1128 else return fBufferSize;
1129}
1130
1131
1132////////////////////////////////////////////////////////////////////////////////
1133/// Return pointer to key with name,cycle
1134///
1135/// if cycle = 9999 returns highest cycle
1137TKey *TDirectoryFile::GetKey(const char *name, Short_t cycle) const
1138{
1139 if (!fKeys) return nullptr;
1140
1141 auto listOfKeys = dynamic_cast<THashList *>(GetListOfKeys());
1142 if (!listOfKeys) {
1143 Error("GetKey", "Unexpected type of TDirectoryFile::fKeys!");
1144 return nullptr;
1145 }
1146
1147 if (const TList *keyList = listOfKeys->GetListForObject(name)) {
1148 for (auto key: TRangeDynCast<TKey>(*keyList)) {
1149 if (key && !strcmp(key->GetName(), name)
1150 && (cycle == 9999 || cycle >= key->GetCycle())) {
1151 return key;
1152 }
1153 }
1154 }
1155
1156 return nullptr;
1157}
1158
1159////////////////////////////////////////////////////////////////////////////////
1160/// List Directory contents
1161///
1162/// Indentation is used to identify the directory tree
1163/// Subdirectories are listed first, then objects in memory, then objects on the file
1164///
1165/// The option can has the following format: <b>`[-d |-m][<regexp>]`</b>
1166/// Options:
1167/// - -d: only list objects in the file
1168/// - -m: only list objects in memory
1169/// The `<regexp>` will be used to match the name of the objects.
1170/// By default memory and disk objects are listed.
1173{
1175 std::cout <<ClassName()<<"*\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
1177
1178 TString opta = option;
1179 TString opt = opta.Strip(TString::kBoth);
1180 Bool_t memobj = kTRUE;
1181 Bool_t diskobj = kTRUE;
1182 TString reg;
1183 if (opt.BeginsWith("-m")) {
1184 diskobj = kFALSE;
1185 if (opt.Length() > 2) {
1186 reg = opt(2,opt.Length());
1187 }
1188 } else if (opt.BeginsWith("-d")) {
1189 memobj = kFALSE;
1190 if (opt.Length() > 2) {
1191 reg = opt(2,opt.Length());
1192 }
1193 } else if (!opt.IsNull()) {
1194 reg = opt;
1195 }
1196
1197 TRegexp re(reg, kTRUE);
1198
1199 if (memobj) {
1200 TObject *obj;
1201 TIter nextobj(fList);
1202 while ((obj = (TObject *) nextobj())) {
1203 TString s = obj->GetName();
1204 if (!reg.IsNull() && s.Index(re) == kNPOS)
1205 continue;
1206 obj->ls(option); //*-* Loop on all the objects in memory
1207 }
1208 }
1209
1210 if (diskobj && fKeys) {
1211 //*-* Loop on all the keys
1212 for (TObjLink *lnk = fKeys->FirstLink(); lnk != nullptr; lnk = lnk->Next()) {
1213 TKey *key = (TKey*)lnk->GetObject();
1214 TString s = key->GetName();
1215 if (!reg.IsNull() && s.Index(re) == kNPOS)
1216 continue;
1217 bool first = (lnk->Prev() == nullptr) || (s != lnk->Prev()->GetObject()->GetName());
1218 bool hasbackup = (lnk->Next() != nullptr) && (s == lnk->Next()->GetObject()->GetName());
1219 if (first)
1220 if (hasbackup)
1221 key->ls(true);
1222 else
1223 key->ls();
1224 else
1225 key->ls(false);
1226 }
1227 }
1229}
1230
1231////////////////////////////////////////////////////////////////////////////////
1232/// Interface to TFile::Open
1234TFile *TDirectoryFile::OpenFile(const char *name, Option_t *option,const char *ftitle, Int_t compress, Int_t netopt)
1235{
1236 return TFile::Open(name,option,ftitle,compress,netopt);
1237
1238}
1239
1240////////////////////////////////////////////////////////////////////////////////
1241/// Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
1242///
1243/// Returns 0 in case of error or if a sub-directory (hierarchy) with the requested
1244/// name already exists.
1245/// returnExistingDirectory returns a pointer to an already existing sub-directory instead of 0.
1246/// Returns a pointer to the created sub-directory or to the top sub-directory of
1247/// the hierarchy (in the above example, the returned TDirectory * always points
1248/// to "a").
1250TDirectory *TDirectoryFile::mkdir(const char *name, const char *title, Bool_t returnExistingDirectory)
1251{
1252 if (!name || !title || !name[0]) return nullptr;
1253 if (!title[0]) title = name;
1254 if (GetKey(name)) {
1255 if (returnExistingDirectory)
1256 return (TDirectoryFile*) GetDirectory(name);
1257 else {
1258 Error("mkdir","An object with name %s exists already",name);
1259 return nullptr;
1260 }
1261 }
1262 TDirectoryFile *newdir = nullptr;
1263 if (const char *slash = strchr(name,'/')) {
1264 TString workname(name, Long_t(slash-name));
1265 TDirectoryFile *tmpdir = nullptr;
1266 GetObject(workname.Data(), tmpdir);
1267 if (!tmpdir) {
1268 tmpdir = (TDirectoryFile*)mkdir(workname.Data(),title);
1269 if (!tmpdir) return nullptr;
1270 }
1271 if (!newdir) newdir = tmpdir;
1272 tmpdir->mkdir(slash+1);
1273 return newdir;
1274 }
1275
1276 TDirectory::TContext ctxt(this);
1277
1278 newdir = new TDirectoryFile(name, title, "", this);
1279
1280 return newdir;
1281}
1282
1283////////////////////////////////////////////////////////////////////////////////
1284/// Purge lowest key cycles in a directory.
1285///
1286/// By default, only the highest cycle of a key is kept. Keys for which
1287/// the "KEEP" flag has been set are not removed. See TKey::Keep().
1288/// NOTE: This does not reduce the size of a TFile--
1289/// the space is simply freed up to be overwritten.
1292{
1293 if (!IsWritable()) return;
1294
1295 TDirectory::TContext ctxt(this);
1296
1297 TKey *key;
1299
1300 while ((key = (TKey*)prev())) { // reverse loop on keys
1301 TKey *keyprev = (TKey*)GetListOfKeys()->Before(key);
1302 if (!keyprev) break;
1303 if (key->GetKeep() == 0) {
1304 if (strcmp(key->GetName(), keyprev->GetName()) == 0) {
1305 key->Delete(); // Remove from the file.
1306 delete key; // Remove from memory.
1307 }
1308 }
1309 }
1310 TFile *f = GetFile();
1311 if (fModified && f) {
1312 WriteKeys(); // Write new keys structure
1313 WriteDirHeader(); // Write new directory header
1314 f->WriteFree(); // Write new free segments list
1315 f->WriteHeader(); // Write new file header
1316 }
1317}
1318
1319////////////////////////////////////////////////////////////////////////////////
1320/// Read objects from a ROOT file directory into memory.
1321///
1322/// If an object is already in memory, the memory copy is deleted
1323/// and the object is again read from the file.
1324/// If opt=="dirs", only subdirectories will be read
1325/// If opt=="dirs*" complete directory tree will be read
1328{
1329 TDirectory::TContext ctxt(this);
1330
1331 TKey *key;
1332 TIter next(GetListOfKeys());
1333
1334 Bool_t readdirs = ((opt!=0) && ((strcmp(opt,"dirs")==0) || (strcmp(opt,"dirs*")==0)));
1335
1336 if (readdirs)
1337 while ((key = (TKey *) next())) {
1338
1339 //if (strcmp(key->GetClassName(),"TDirectory")!=0) continue;
1340 if (strstr(key->GetClassName(),"TDirectory")==0) continue;
1341
1342 TDirectory *dir = GetDirectory(key->GetName(), kTRUE, "ReadAll");
1343
1344 if ((dir!=0) && (strcmp(opt,"dirs*")==0)) dir->ReadAll("dirs*");
1345 }
1346 else
1347 while ((key = (TKey *) next())) {
1348 TObject *thing = GetList()->FindObject(key->GetName());
1349 if (thing) { delete thing; }
1350 key->ReadObj();
1351 }
1352}
1353
1354////////////////////////////////////////////////////////////////////////////////
1355/// Read the linked list of keys.
1356///
1357/// Every directory has a linked list (fKeys). This linked list has been
1358/// written on the file via WriteKeys as a single data record.
1359///
1360/// It is interesting to call this function in the following situation.
1361/// Assume another process1 is connecting this directory in Update mode
1362/// - Process1 is adding/updating objects in this directory
1363/// - You want to see the latest status from process1.
1364/// Example Process1:
1365/// ~~~{.cpp}
1366/// obj1.Write();
1367/// obj2.Write();
1368/// gDirectory->SaveSelf();
1369/// ~~~
1370///
1371/// Example Process2:
1372/// ~~~{.cpp}
1373/// gDirectory->ReadKeys();
1374/// obj1->Draw();
1375/// ~~~
1376/// This is an efficient way (without opening/closing files) to view
1377/// the latest updates of a file being modified by another process
1378/// as it is typically the case in a data acquisition system.
1381{
1382 if (!fFile || !fKeys) return 0;
1383
1384 if (!fFile->IsBinary())
1385 return fFile->DirReadKeys(this);
1386
1387 TDirectory::TContext ctxt(this);
1388
1389 char *buffer;
1390 if (forceRead) {
1391 fKeys->Delete();
1392 //In case directory was updated by another process, read new
1393 //position for the keys
1395 char *header = new char[nbytes];
1396 buffer = header;
1398 if ( fFile->ReadBuffer(buffer,nbytes) ) {
1399 // ReadBuffer return kTRUE in case of failure.
1400 delete [] header;
1401 return 0;
1402 }
1403 buffer += fNbytesName;
1404 Version_t versiondir;
1405 frombuf(buffer,&versiondir);
1406 fDatimeC.ReadBuffer(buffer);
1407 fDatimeM.ReadBuffer(buffer);
1408 frombuf(buffer, &fNbytesKeys);
1409 frombuf(buffer, &fNbytesName);
1410 if (versiondir > 1000) {
1411 frombuf(buffer, &fSeekDir);
1412 frombuf(buffer, &fSeekParent);
1413 frombuf(buffer, &fSeekKeys);
1414 } else {
1415 Int_t sdir,sparent,skeys;
1416 frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir;
1417 frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent;
1418 frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys;
1419 }
1420 delete [] header;
1421 }
1422
1423 Int_t nkeys = 0;
1424 Long64_t fsize = fFile->GetSize();
1425 if ( fSeekKeys > 0) {
1426 TKey *headerkey = new TKey(fSeekKeys, fNbytesKeys, this);
1427 headerkey->ReadFile();
1428 buffer = headerkey->GetBuffer();
1429 headerkey->ReadKeyBuffer(buffer);
1430
1431 TKey *key;
1432 frombuf(buffer, &nkeys);
1433 for (Int_t i = 0; i < nkeys; i++) {
1434 key = new TKey(this);
1435 key->ReadKeyBuffer(buffer);
1436 if (key->GetSeekKey() < 64 || key->GetSeekKey() > fsize) {
1437 Error("ReadKeys","reading illegal key, exiting after %d keys",i);
1438 fKeys->Remove(key);
1439 nkeys = i;
1440 break;
1441 }
1442 if (key->GetSeekPdir() < 64 || key->GetSeekPdir() > fsize) {
1443 Error("ReadKeys","reading illegal key, exiting after %d keys",i);
1444 fKeys->Remove(key);
1445 nkeys = i;
1446 break;
1447 }
1448 fKeys->Add(key);
1449 }
1450 delete headerkey;
1451 }
1452
1453 return nkeys;
1454}
1455
1456
1457////////////////////////////////////////////////////////////////////////////////
1458/// Read object with keyname from the current directory
1459///
1460/// Read contents of object with specified name from the current directory.
1461/// First the key with keyname is searched in the current directory,
1462/// next the key buffer is deserialized into the object.
1463/// The object must have been created before via the default constructor.
1464/// See TObject::Write().
1466Int_t TDirectoryFile::ReadTObject(TObject *obj, const char *keyname)
1467{
1468 if (!fFile) { Error("ReadTObject","No file open"); return 0; }
1469 auto listOfKeys = dynamic_cast<THashList *>(GetListOfKeys());
1470 if (!listOfKeys) {
1471 Error("ReadTObject", "Unexpected type of TDirectoryFile::fKeys!");
1472 return 0;
1473 }
1474
1475 if (const TList *keyList = listOfKeys->GetListForObject(keyname)) {
1476 for (auto key: TRangeDynCast<TKey>(*keyList)) {
1477 if (key && !strcmp(key->GetName(), keyname) ) {
1478 return key->Read(obj);
1479 }
1480 }
1481 }
1482
1483 Error("ReadTObject","Key not found");
1484 return 0;
1485}
1486
1487////////////////////////////////////////////////////////////////////////////////
1488/// Reset the TDirectory after its content has been merged into another
1489/// Directory.
1490///
1491/// This returns the TDirectoryFile object back to its state
1492/// before any data has been written to the file.
1493/// The object in the in-memory list are assumed to also have been reset.
1496{
1497 // There is nothing to reset in the base class (TDirectory) since
1498 // we do want to key the list of in-memory object as is.
1499 fModified = kFALSE;
1500 // Does not change: fWritable
1501 fDatimeC.Set();
1502 fDatimeM.Set();
1503 fNbytesKeys = 0; // updated when the keys are written
1504 fNbytesName = 0; // updated by Init
1505 // Does not change (user customization): fBufferSize;
1506 fSeekDir = 0; // updated by Init
1507 fSeekParent = 0; // updated by Init
1508 fSeekKeys = 0; // updated by Init
1509 // Does not change: fFile
1510 TKey *key = fKeys ? (TKey*)fKeys->FindObject(fName) : nullptr;
1511 TClass *cl = IsA();
1512 if (key) {
1513 cl = TClass::GetClass(key->GetClassName());
1514 }
1515 // NOTE: We should check that the content is really mergeable and in
1516 // the in-mmeory list, before deleting the keys.
1517 if (fKeys) {
1518 fKeys->Delete("slow");
1519 }
1520
1522
1523 // Do the same with the sub-directories.
1524 TIter next(GetList());
1525 TObject *idcur;
1526 while ((idcur = next())) {
1527 if (idcur->IsA() == TDirectoryFile::Class()) {
1528 ((TDirectoryFile*)idcur)->ResetAfterMerge(info);
1529 }
1530 }
1531
1532}
1533
1534////////////////////////////////////////////////////////////////////////////////
1535/// Removes subdirectory from the directory
1536///
1537/// When directory is deleted, all keys in all subdirectories will be
1538/// read first and deleted from file (if exists)
1539/// Equivalent call is Delete("name;*");
1541void TDirectoryFile::rmdir(const char *name)
1542{
1543 if (!name || (*name==0)) return;
1544
1545 TString mask(name);
1546 mask += ";*";
1547 Delete(mask);
1548}
1549
1550////////////////////////////////////////////////////////////////////////////////
1551/// Save recursively all directory keys and headers
1554{
1555 TDirectory::TContext ctxt(this);
1556
1557 SaveSelf();
1558
1559 // recursively save all sub-directories
1560 if (fList && fList->FirstLink()) {
1561 auto lnk = fList->FirstLink()->shared_from_this();
1562 while (lnk) {
1563 TObject *idcur = lnk->GetObject();
1564 if (idcur && idcur->InheritsFrom(TDirectoryFile::Class())) {
1565 TDirectoryFile *dir = (TDirectoryFile *)idcur;
1566 dir->Save();
1567 }
1568 lnk = lnk->NextSP();
1569 }
1570 }
1571}
1572
1573////////////////////////////////////////////////////////////////////////////////
1574/// Save object in filename.
1575///
1576/// If filename is `nullptr` or "", a file with "<objectname>.root" is created.
1577/// The name of the key is the object name.
1578/// By default new file will be created. Using option "a", one can append object
1579/// to the existing ROOT file.
1580/// If the operation is successful, it returns the number of bytes written to the file
1581/// otherwise it returns 0.
1582/// By default a message is printed. Use option "q" to not print the message.
1583/// If filename contains ".json" extension, JSON representation of the object
1584/// will be created and saved in the text file. Such file can be used in
1585/// JavaScript ROOT (https://root.cern/js/) to display object in web browser
1586/// When creating JSON file, option string may contain compression level from 0 to 3 (default 0)
1588Int_t TDirectoryFile::SaveObjectAs(const TObject *obj, const char *filename, Option_t *option) const
1589{
1590 // option can contain single letter args: "a" for append, "q" for quiet in any combinations
1591
1592 if (!obj) return 0;
1593 TString fname, opt = option;
1594 if (filename && *filename)
1595 fname = filename;
1596 else
1597 fname.Form("%s.root", obj->GetName());
1598 opt.ToLower();
1599
1600 Int_t nbytes = 0;
1601 if (fname.Index(".json") > 0) {
1602 nbytes = TBufferJSON::ExportToFile(fname, obj, option);
1603 } else {
1604 TContext ctxt; // The TFile::Open will change the current directory.
1605 auto *local = TFile::Open(fname.Data(), opt.Contains("a") ? "update" : "recreate");
1606 if (!local) return 0;
1607 nbytes = obj->Write();
1608 delete local;
1609 }
1610 if (!opt.Contains("q") && !gSystem->AccessPathName(fname.Data()))
1611 obj->Info("SaveAs", "ROOT file %s has been created", fname.Data());
1612 return nbytes;
1613}
1614
1615////////////////////////////////////////////////////////////////////////////////
1616/// Save Directory keys and header
1617///
1618/// If the directory has been modified (fModified set), write the keys
1619/// and the directory header. This function assumes the cd is correctly set.
1620///
1621/// It is recommended to use this function in the following situation:
1622/// Assume a process1 using a directory in Update mode
1623/// - New objects or modified objects have been written to the directory.
1624/// - You do not want to close the file.
1625/// - You want your changes be visible from another process2 already connected
1626/// to this directory in read mode.
1627/// - Call this function.
1628/// - In process2, use TDirectoryFile::ReadKeys to refresh the directory.
1631{
1632 if (IsWritable() && (fModified || force) && fFile) {
1633 Bool_t dowrite = kTRUE;
1634 if (fFile->GetListOfFree())
1635 dowrite = fFile->GetListOfFree()->First() != nullptr;
1636 if (dowrite) {
1637 TDirectory *dirsav = gDirectory;
1638 if (dirsav != this) cd();
1639 WriteKeys(); //*-*- Write keys record
1640 WriteDirHeader(); //*-*- Update directory record
1641 if (dirsav && dirsav != this) dirsav->cd();
1642 }
1643 }
1644}
1645
1646////////////////////////////////////////////////////////////////////////////////
1647/// Set the default buffer size when creating new TKeys.
1648///
1649/// See also TDirectoryFile::GetBufferSize
1652{
1653 fBufferSize = bufsize;
1654}
1655
1656////////////////////////////////////////////////////////////////////////////////
1657/// Find the action to be executed in the dictionary of the parent class
1658/// and store the corresponding exec number into fBits.
1659///
1660/// This function searches a data member in the class of parent with an
1661/// offset corresponding to this.
1662/// If a comment "TEXEC:" is found in the comment field of the data member,
1663/// the function stores the exec identifier of the exec statement
1664/// following this keyword.
1667{
1668 Int_t offset = (char*)ref - (char*)parent;
1669 TClass *cl = parent->IsA();
1670 cl->BuildRealData(parent);
1672 TIter next(info->GetElements());
1673 TStreamerElement *element;
1674 while((element = (TStreamerElement*)next())) {
1675 if (element->GetOffset() != offset) continue;
1676 Int_t execid = element->GetExecID();
1677 if (execid > 0) ref->SetBit(execid << 8);
1678 return;
1679 }
1680}
1681
1682////////////////////////////////////////////////////////////////////////////////
1683/// Set the new value of fWritable recursively
1686{
1687 TDirectory::TContext ctxt(this);
1688
1689 fWritable = writable;
1690
1691 // recursively set all sub-directories
1692 if (fList) {
1693 TObject *idcur;
1694 TIter next(fList);
1695 while ((idcur = next())) {
1696 if (idcur->InheritsFrom(TDirectoryFile::Class())) {
1697 TDirectoryFile *dir = (TDirectoryFile*)idcur;
1698 dir->SetWritable(writable);
1699 }
1700 }
1701 }
1702}
1703
1704
1705////////////////////////////////////////////////////////////////////////////////
1706/// Return the size in bytes of the directory header
1709{
1710 Int_t nbytes = 22;
1711
1712 nbytes += fDatimeC.Sizeof();
1713 nbytes += fDatimeM.Sizeof();
1714 nbytes += fUUID.Sizeof();
1715 //assume that the file may be above 2 Gbytes if file version is > 4
1716 if (fFile && fFile->GetVersion() >= 40000) nbytes += 12;
1717 return nbytes;
1718}
1719
1720
1721////////////////////////////////////////////////////////////////////////////////
1722/// Stream a class object
1725{
1726 Version_t v,version;
1727 if (b.IsReading()) {
1728 BuildDirectoryFile((TFile*)b.GetParent(), nullptr);
1729 if (fFile && fFile->IsWritable()) fWritable = kTRUE;
1730
1731 if (fFile && !fFile->IsBinary()) {
1732 Version_t R__v = b.ReadVersion(0, 0);
1733
1734 TClass* dirclass = (R__v < 5) ? TDirectory::Class() : TDirectoryFile::Class();
1735
1736 b.ClassBegin(dirclass, R__v);
1737
1738 TString sbuf;
1739
1740 b.ClassMember("CreateTime","TString");
1741 sbuf.Streamer(b);
1742 TDatime timeC(sbuf.Data());
1743 fDatimeC = timeC;
1744
1745 b.ClassMember("ModifyTime","TString");
1746 sbuf.Streamer(b);
1747 TDatime timeM(sbuf.Data());
1748 fDatimeM = timeM;
1749
1750 b.ClassMember("UUID","TString");
1751 sbuf.Streamer(b);
1752 TUUID id(sbuf.Data());
1753 fUUID = id;
1754
1755 b.ClassEnd(dirclass);
1756
1757 fSeekKeys = 0; // read keys later in the TKeySQL class
1758 } else {
1759 b >> version;
1762 b >> fNbytesKeys;
1763 b >> fNbytesName;
1764 if (version > 1000) {
1766 b >> fSeekDir;
1767 b >> fSeekParent;
1768 b >> fSeekKeys;
1769 } else {
1770 Int_t sdir,sparent,skeys;
1771 b >> sdir; fSeekDir = (Long64_t)sdir;
1772 b >> sparent; fSeekParent = (Long64_t)sparent;
1773 b >> skeys; fSeekKeys = (Long64_t)skeys;
1774 }
1775 v = version%1000;
1776 if (v == 2) {
1778 } else if (v > 2) {
1779 fUUID.Streamer(b);
1780 }
1781 }
1782 fList->UseRWLock();
1784 gROOT->GetUUIDs()->AddUUID(fUUID,this);
1785 if (fSeekKeys) ReadKeys();
1786 } else {
1787 if (fFile && !fFile->IsBinary()) {
1788 b.WriteVersion(TDirectoryFile::Class());
1789
1790 TString sbuf;
1791
1792 b.ClassBegin(TDirectoryFile::Class());
1793
1794 b.ClassMember("CreateTime","TString");
1795 sbuf = fDatimeC.AsSQLString();
1796 sbuf.Streamer(b);
1797
1798 b.ClassMember("ModifyTime","TString");
1799 fDatimeM.Set();
1800 sbuf = fDatimeM.AsSQLString();
1801 sbuf.Streamer(b);
1802
1803 b.ClassMember("UUID","TString");
1804 sbuf = fUUID.AsString();
1805 sbuf.Streamer(b);
1806
1807 b.ClassEnd(TDirectoryFile::Class());
1808 } else {
1810 if (fFile && fFile->GetEND() > TFile::kStartBigFile) version += 1000;
1811 b << version;
1814 b << fNbytesKeys;
1815 b << fNbytesName;
1816 if (version > 1000) {
1817 b << fSeekDir;
1818 b << fSeekParent;
1819 b << fSeekKeys;
1820 } else {
1821 b << (Int_t)fSeekDir;
1822 b << (Int_t)fSeekParent;
1823 b << (Int_t)fSeekKeys;
1824 }
1825 fUUID.Streamer(b);
1826 if (version <=1000) for (Int_t i=0;i<3;i++) b << Int_t(0);
1827 }
1828 }
1829}
1830
1831////////////////////////////////////////////////////////////////////////////////
1832/// Write all objects in memory to disk.
1833///
1834/// Loop on all objects in memory (including subdirectories).
1835/// A new key is created in the keys linked list for each object.
1836/// For allowed options see TObject::Write().
1837/// The directory header info is rewritten on the directory header record.
1839Int_t TDirectoryFile::Write(const char *, Int_t opt, Int_t bufsize)
1840{
1841 if (!IsWritable()) return 0;
1842 TDirectory::TContext ctxt(this);
1843
1844 // Loop on all objects (including subdirs)
1845 TIter next(fList);
1846 TObject *obj;
1847 Int_t nbytes = 0;
1848 while ((obj=next())) {
1849 nbytes += obj->Write(0,opt,bufsize);
1850 }
1851 if (R__likely(!(opt & kOnlyPrepStep)))
1852 SaveSelf(kTRUE); // force save itself
1853
1854 return nbytes;
1855}
1856
1857////////////////////////////////////////////////////////////////////////////////
1858/// One can not save a const TDirectory object.
1860Int_t TDirectoryFile::Write(const char *n, Int_t opt, Int_t bufsize) const
1861{
1862 Error("Write const","A const TDirectory object should not be saved. We try to proceed anyway.");
1863 return const_cast<TDirectoryFile*>(this)->Write(n, opt, bufsize);
1864}
1865
1866////////////////////////////////////////////////////////////////////////////////
1867/// Write object obj to this directory.
1868///
1869/// The data structure corresponding to this object is serialized.
1870/// The corresponding buffer is written to this directory
1871/// with an associated key with name "name".
1872///
1873/// Writing an object to a file involves the following steps:
1874/// - Creation of a support TKey object in the directory. The TKey object
1875/// creates a TBuffer object.
1876/// - The TBuffer object is filled via the class::Streamer function.
1877/// - If the file is compressed (default) a second buffer is created to hold
1878/// the compressed buffer.
1879/// - Reservation of the corresponding space in the file by looking in the
1880/// TFree list of free blocks of the file.
1881/// - The buffer is written to the file.
1882///
1883/// By default, the buffersize will be taken from the average buffer size
1884/// of all objects written to the current file so far.
1885/// Use TDirectoryFile::SetBufferSize to force a given buffer size.
1886///
1887/// If a name is specified, it will be the name of the key.
1888/// If name is not given, the name of the key will be the name as returned
1889/// by obj->GetName().
1890///
1891/// The option can be a combination of:
1892/// - "SingleKey"
1893/// - "Overwrite"
1894/// - "WriteDelete"
1895/// Using the "Overwrite" option a previous key with the same name is
1896/// overwritten. The previous key is deleted before writing the new object.
1897/// Using the "WriteDelete" option a previous key with the same name is
1898/// deleted only after the new object has been written. This option
1899/// is safer than kOverwrite but it is slower.
1900/// The "SingleKey" option is only used by TCollection::Write() to write
1901/// a container with a single key instead of each object in the container
1902/// with its own key.
1903/// An object is read from this directory via TDirectoryFile::Get.
1904/// The function returns the total number of bytes written to the directory.
1905/// It returns 0 if the object cannot be written.
1906///
1907/// WARNING: avoid special characters like '^','$','.' in the name as they
1908/// are used by the regular expression parser (see TRegexp).
1910Int_t TDirectoryFile::WriteTObject(const TObject *obj, const char *name, Option_t *option, Int_t bufsize)
1911{
1912 TDirectory::TContext ctxt(this);
1913
1914 if (fFile==0) {
1915 const char *objname = "no name specified";
1916 if (name) objname = name;
1917 else if (obj) objname = obj->GetName();
1918 Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
1919 return 0;
1920 }
1921
1922 if (!fFile->IsWritable()) {
1924 // Do not print the error if the file already had a SysError.
1925 Error("WriteTObject","Directory %s is not writable", fFile->GetName());
1926 }
1927 return 0;
1928 }
1929
1930 if (!obj) return 0;
1931
1932 TString opt = option;
1933 opt.ToLower();
1934
1935 TKey *key=0, *oldkey=0;
1936 Int_t bsize = GetBufferSize();
1937 if (bufsize > 0) bsize = bufsize;
1938
1939 const char *oname;
1940 if (name && *name)
1941 oname = name;
1942 else
1943 oname = obj->GetName();
1944
1945 // Remove trailing blanks in object name
1946 Int_t nch = strlen(oname);
1947 char *newName = nullptr;
1948 if (nch && oname[nch-1] == ' ') {
1949 newName = new char[nch+1];
1950 strlcpy(newName,oname,nch+1);
1951 for (Int_t i=0;i<nch;i++) {
1952 if (newName[nch-i-1] != ' ') break;
1953 newName[nch-i-1] = 0;
1954 }
1955 oname = newName;
1956 }
1957
1958 if (opt.Contains("overwrite")) {
1959 //One must use GetKey. FindObject would return the lowest cycle of the key!
1960 //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname);
1961 key = GetKey(oname);
1962 if (key) {
1963 key->Delete();
1964 delete key;
1965 }
1966 }
1967 if (opt.Contains("writedelete")) {
1968 oldkey = GetKey(oname);
1969 }
1970 key = fFile->CreateKey(this, obj, oname, bsize);
1971 if (newName) delete [] newName;
1972
1973 if (!key->GetSeekKey()) {
1974 fKeys->Remove(key);
1975 delete key;
1976 if (bufsize) fFile->SetBufferSize(bufsize);
1977 return 0;
1978 }
1979 fFile->SumBuffer(key->GetObjlen());
1980 Int_t nbytes = key->WriteFile(0);
1982 if (bufsize) fFile->SetBufferSize(bufsize);
1983 return 0;
1984 }
1985 if (oldkey) {
1986 oldkey->Delete();
1987 delete oldkey;
1988 }
1989 if (bufsize) fFile->SetBufferSize(bufsize);
1990
1991 return nbytes;
1992}
1993
1994////////////////////////////////////////////////////////////////////////////////
1995/// Write object from pointer of class classname in this directory.
1996///
1997/// obj may not derive from TObject. See TDirectoryFile::WriteTObject for comments
1998///
1999/// ## Very important note
2000/// The value passed as 'obj' needs to be from a pointer to the type described by classname.
2001/// For example:
2002/// ~~~{.cpp}
2003/// TopClass *top;
2004/// BottomClass *bottom;
2005/// top = bottom;
2006/// ~~~
2007/// you can do:
2008/// ~~~{.cpp}
2009/// directory->WriteObjectAny(top,"top","name of object");
2010/// directory->WriteObjectAny(bottom,"bottom","name of object");
2011/// ~~~
2012/// <b>BUT YOU CAN NOT DO</b> the following since it will fail with multiple inheritance:
2013/// ~~~{.cpp}
2014/// directory->WriteObjectAny(top,"bottom","name of object");
2015/// ~~~
2016/// We <b>STRONGLY</b> recommend to use
2017/// ~~~{.cpp}
2018/// TopClass *top = ....;
2019/// directory->WriteObject(top,"name of object")
2020/// ~~~
2021/// See also remarks in TDirectoryFile::WriteTObject
2023Int_t TDirectoryFile::WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option, Int_t bufsize)
2024{
2025 TClass *cl = TClass::GetClass(classname);
2026 if (!cl) {
2027 TObject *info_obj = *(TObject**)obj;
2028 TVirtualStreamerInfo *info = dynamic_cast<TVirtualStreamerInfo*>(info_obj);
2029 if (!info) {
2030 Error("WriteObjectAny","Unknown class: %s",classname);
2031 return 0;
2032 } else {
2033 cl = info->GetClass();
2034 }
2035 }
2036 return WriteObjectAny(obj,cl,name,option,bufsize);
2037}
2038
2039////////////////////////////////////////////////////////////////////////////////
2040/// Write object of class with dictionary cl in this directory.
2041///
2042/// obj may not derive from TObject
2043/// To get the TClass* cl pointer, one can use
2044///
2045/// TClass *cl = TClass::GetClass("classname");
2046///
2047/// An alternative is to call the function WriteObjectAny above.
2048/// see TDirectoryFile::WriteTObject for comments
2050Int_t TDirectoryFile::WriteObjectAny(const void *obj, const TClass *cl, const char *name, Option_t *option, Int_t bufsize)
2051{
2052 TDirectory::TContext ctxt(this);
2053
2054 if (!fFile) return 0;
2055
2056 if (!cl) {
2057 Error("WriteObject","Unknown type for %s, it can not be written.",name);
2058 return 0;
2059 }
2060
2061 if (!fFile->IsWritable()) {
2063 // Do not print the error if the file already had a SysError.
2064 Error("WriteObject","File %s is not writable", fFile->GetName());
2065 }
2066 return 0;
2067 }
2068
2069 if (!obj) return 0;
2070
2071 const char *className = cl->GetName();
2072 const char *oname;
2073 if (name && *name)
2074 oname = name;
2075 else
2076 oname = className;
2077
2078 if (cl && cl->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(cl->GetCollectionProxy())) {
2079 Error("WriteObjectAny",
2080 "The class requested (%s) for the key name \"%s\""
2081 " is an instance of an stl collection and does not have a compiled CollectionProxy."
2082 " Please generate the dictionary for this collection (%s). No data will be written.",
2083 className, oname, className);
2084 return 0;
2085 }
2086
2087 TKey *key, *oldkey = nullptr;
2088 Int_t bsize = GetBufferSize();
2089 if (bufsize > 0) bsize = bufsize;
2090
2091 TString opt = option;
2092 opt.ToLower();
2093
2094 // Remove trailing blanks in object name
2095 Int_t nch = strlen(oname);
2096 char *newName = nullptr;
2097 if (nch && oname[nch-1] == ' ') {
2098 newName = new char[nch+1];
2099 strlcpy(newName,oname,nch+1);
2100 for (Int_t i=0;i<nch;i++) {
2101 if (newName[nch-i-1] != ' ') break;
2102 newName[nch-i-1] = 0;
2103 }
2104 oname = newName;
2105 }
2106
2107 if (opt.Contains("overwrite")) {
2108 //One must use GetKey. FindObject would return the lowest cycle of the key!
2109 //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname);
2110 key = GetKey(oname);
2111 if (key) {
2112 key->Delete();
2113 delete key;
2114 }
2115 }
2116 if (opt.Contains("writedelete")) {
2117 oldkey = GetKey(oname);
2118 }
2119 key = fFile->CreateKey(this, obj, cl, oname, bsize);
2120 if (newName) delete [] newName;
2121
2122 if (!key->GetSeekKey()) {
2123 fKeys->Remove(key);
2124 delete key;
2125 return 0;
2126 }
2127 fFile->SumBuffer(key->GetObjlen());
2128 Int_t nbytes = key->WriteFile(0);
2129 if (fFile->TestBit(TFile::kWriteError)) return 0;
2130
2131 if (oldkey) {
2132 oldkey->Delete();
2133 delete oldkey;
2134 }
2135
2136 return nbytes;
2137}
2138
2139////////////////////////////////////////////////////////////////////////////////
2140/// Overwrite the Directory header record.
2143{
2144 TFile* f = GetFile();
2145 if (!f) return;
2146
2147 if (!f->IsBinary()) {
2148 fDatimeM.Set();
2149 f->DirWriteHeader(this);
2150 return;
2151 }
2152
2153 Int_t nbytes = TDirectoryFile::Sizeof(); //Warning ! TFile has a Sizeof()
2154 char *header = new char[nbytes];
2155 char *buffer = header;
2156 fDatimeM.Set();
2158 Long64_t pointer = fSeekDir + fNbytesName; // do not overwrite the name/title part
2159 fModified = kFALSE;
2160 f->Seek(pointer);
2161 f->WriteBuffer(header, nbytes);
2162 if (f->MustFlush()) f->Flush();
2163 delete [] header;
2164}
2165
2166////////////////////////////////////////////////////////////////////////////////
2167/// Write Keys linked list on the file.
2168///
2169/// The linked list of keys (fKeys) is written as a single data record
2172{
2173 TFile* f = GetFile();
2174 if (!f) return;
2175
2176 if (!f->IsBinary()) {
2177 f->DirWriteKeys(this);
2178 return;
2179 }
2180
2181//*-* Delete the old keys structure if it exists
2182 if (fSeekKeys != 0) {
2183 f->MakeFree(fSeekKeys, fSeekKeys + fNbytesKeys -1);
2184 }
2185//*-* Write new keys record
2186 TIter next(fKeys);
2187 TKey *key;
2188 Int_t nkeys = fKeys->GetSize();
2189 Int_t nbytes = sizeof nkeys; //*-* Compute size of all keys
2190 if (f->GetEND() > TFile::kStartBigFile) nbytes += 8;
2191 while ((key = (TKey*)next())) {
2192 nbytes += key->Sizeof();
2193 }
2194 TKey *headerkey = new TKey(fName,fTitle,IsA(),nbytes,this);
2195 if (headerkey->GetSeekKey() == 0) {
2196 delete headerkey;
2197 return;
2198 }
2199 char *buffer = headerkey->GetBuffer();
2200 next.Reset();
2201 tobuf(buffer, nkeys);
2202 while ((key = (TKey*)next())) {
2203 key->FillBuffer(buffer);
2204 }
2205
2206 fSeekKeys = headerkey->GetSeekKey();
2207 fNbytesKeys = headerkey->GetNbytes();
2208 headerkey->WriteFile();
2209 delete headerkey;
2210}
void frombuf(char *&buf, Bool_t *x)
Definition Bytes.h:278
void tobuf(char *&buf, Bool_t x)
Definition Bytes.h:55
#define R__likely(expr)
Definition RConfig.hxx:587
#define SafeDelete(p)
Definition RConfig.hxx:525
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:117
long long Long64_t
Definition RtypesCore.h:69
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:90
#define ClassImp(name)
Definition Rtypes.h:382
const Bool_t kIterBackward
Definition TCollection.h:43
const Int_t kMaxLen
const UInt_t kIsBigFile
const Int_t kMaxLen
#define gDirectory
Definition TDirectory.h:384
#define gFile
Definition TFile.h:347
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void reg
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Definition TROOT.cxx:597
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
#define R__LOCKGUARD(mutex)
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
void MapObject(const TObject *obj, UInt_t offset=1) override
Add object to the fMap container.
void ResetMap() override
Delete existing fMap and reset map counter.
static Int_t ExportToFile(const char *filename, const TObject *obj, const char *option=nullptr)
Convert object into JSON and store in text file Returns size of the produce file Used in TObject::Sav...
Buffer base class used for serializing objects.
Definition TBuffer.h:43
@ kWrite
Definition TBuffer.h:73
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
void SetReadMode()
Set buffer in read mode.
Definition TBuffer.cxx:302
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5045
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7554
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2098
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:6005
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4666
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2858
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2964
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3035
static TClass * Class()
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
void FillBuffer(char *&buffer)
Encode Date/Time into buffer, used by I/O system.
Definition TDatime.cxx:229
const char * AsSQLString() const
Return the date & time in SQL compatible string format, like: 1997-01-15 20:16:28.
Definition TDatime.cxx:152
Int_t Sizeof() const
Definition TDatime.h:81
virtual void Streamer(TBuffer &)
Stream a object of type TDatime.
Definition TDatime.cxx:416
void Set()
Set Date/Time to current time as reported by the system.
Definition TDatime.cxx:289
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition TDatime.cxx:278
A ROOT file is structured in Directories (like a file system).
void SetBufferSize(Int_t bufsize) override
Set the default buffer size when creating new TKeys.
void SetTRefAction(TObject *ref, TObject *parent) override
Find the action to be executed in the dictionary of the parent class and store the corresponding exec...
void Close(Option_t *option="") override
Delete all objects from memory and directory structure itself.
Bool_t cd() override
Change current directory to "this" directory.
TFile * fFile
Pointer to current file in memory.
void Browse(TBrowser *b) override
Browse the content of the directory.
void Append(TObject *obj, Bool_t replace=kFALSE) override
Append object to this directory.
void SaveSelf(Bool_t force=kFALSE) override
Save Directory keys and header.
static TClass * Class()
Bool_t IsWritable() const override
void Streamer(TBuffer &) override
Stream a class object.
void Delete(const char *namecycle="") override
Delete Objects or/and keys in a directory.
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset the TDirectory after its content has been merged into another Directory.
Int_t AppendKey(TKey *key) override
Insert key in the linked list of keys of this directory.
Int_t ReadKeys(Bool_t forceRead=kTRUE) override
Read the linked list of keys.
TDatime fDatimeM
Date and time of last modification.
void * GetObjectUnchecked(const char *namecycle) override
Return pointer to object identified by namecycle.
TKey * FindKey(const char *keyname) const override
Find key with name keyname in the current directory.
TKey * GetKey(const char *name, Short_t cycle=9999) const override
Return pointer to key with name,cycle.
void * GetObjectChecked(const char *namecycle, const char *classname) override
See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl)
void InitDirectoryFile(TClass *cl=nullptr)
Initialize the key associated with this directory (and the related data members.
void Purge(Short_t nkeep=1) override
Purge lowest key cycles in a directory.
void Save() override
Save recursively all directory keys and headers.
~TDirectoryFile() override
Destructor.
TObject * FindObjectAnyFile(const char *name) const override
Scan the memory lists of all files for an object with name.
Int_t fNbytesKeys
Number of bytes for the keys.
Bool_t fModified
True if directory has been modified.
TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE) override
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
TList * GetListOfKeys() const override
void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.)
TObject * FindObjectAny(const char *name) const override
Find object by name in the list of memory objects of the current directory or its sub-directories.
Long64_t fSeekKeys
Location of Keys record on file.
void WriteKeys() override
Write Keys linked list on the file.
TFile * GetFile() const override
Int_t fBufferSize
Default buffer size to create new TKeys.
Int_t Sizeof() const override
Return the size in bytes of the directory header.
TObject * CloneObject(const TObject *obj, Bool_t autoadd=kTRUE) override
Make a clone of an object using the Streamer facility.
TDirectory * GetDirectory(const char *apath, Bool_t printError=false, const char *funcname="GetDirectory") override
Find a directory named "apath".
Long64_t fSeekParent
Location of parent directory on file.
Int_t WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option="", Int_t bufsize=0) override
Write object from pointer of class classname in this directory.
void BuildDirectoryFile(TFile *motherFile, TDirectory *motherDir)
Initialise directory to defaults.
void rmdir(const char *name) override
Removes subdirectory from the directory.
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsize=0) override
Write all objects in memory to disk.
Long64_t fSeekDir
Location of directory on file.
Int_t fNbytesName
Number of bytes in TNamed at creation time.
TDatime fDatimeC
Date and time when directory is created.
Bool_t fWritable
True if directory is writable.
Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *option="", Int_t bufsize=0) override
Write object obj to this directory.
Int_t ReadTObject(TObject *obj, const char *keyname) override
Read object with keyname from the current directory.
TFile * OpenFile(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0) override
Interface to TFile::Open.
Int_t GetBufferSize() const override
Return the buffer size to create new TKeys.
Int_t SaveObjectAs(const TObject *obj, const char *filename="", Option_t *option="") const override
Save object in filename.
TObject * Get(const char *namecycle) override
Return pointer to object identified by namecycle.
static constexpr Version_t Class_Version()
TDirectoryFile()
Default TDirectoryFile constructor.
TKey * FindKeyAny(const char *keyname) const override
Find key with name keyname in the current directory or its subdirectories.
void FillBuffer(char *&buffer) override
Encode directory header into output buffer.
void WriteDirHeader() override
Overwrite the Directory header record.
void SetWritable(Bool_t writable=kTRUE) override
Set the new value of fWritable recursively.
TClass * IsA() const override
void ReadAll(Option_t *option="") override
Read objects from a ROOT file directory into memory.
TList * fKeys
Pointer to keys list in memory.
void ls(Option_t *option="") const override
List Directory contents.
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
Describe directory structure in memory.
Definition TDirectory.h:45
static TClass * Class()
void Delete(const char *namecycle="") override
Delete Objects or/and keys in a directory.
virtual TList * GetList() const
Definition TDirectory.h:222
virtual Int_t AppendKey(TKey *)
Definition TDirectory.h:184
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
virtual void ReadAll(Option_t *="")
Definition TDirectory.h:247
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.).
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
static void DecodeNameCycle(const char *namecycle, char *name, Short_t &cycle, const size_t namesize=0)
Decode a namecycle "aap;2" into name "aap" and cycle "2".
virtual TFile * GetFile() const
Definition TDirectory.h:220
TObject * FindObject(const char *name) const override
Find object by name in the list of memory objects.
virtual Bool_t cd()
Change current directory to "this" directory.
TUUID fUUID
Definition TDirectory.h:143
TDirectory * GetMotherDir() const
Definition TDirectory.h:225
TObject * fMother
Definition TDirectory.h:141
void GetObject(const char *namecycle, T *&ptr)
Get an object with proper type checking.
Definition TDirectory.h:212
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
TList * fList
Definition TDirectory.h:142
virtual TKey * FindKeyAny(const char *) const
Definition TDirectory.h:198
virtual TObject * FindObjectAny(const char *name) const
Find object by name in the list of memory objects of the current directory or its sub-directories.
Streamer around an arbitrary STL like container, which implements basic container functionality.
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:53
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
Definition TFile.cxx:2274
Int_t GetVersion() const
Definition TFile.h:245
Bool_t IsBinary() const
Definition TFile.h:259
@ kStartBigFile
Definition TFile.h:200
virtual Int_t DirReadKeys(TDirectory *)
Definition TFile.h:168
TList * GetListOfFree() const
Definition TFile.h:237
Int_t GetBestBuffer() const
Return the best buffer size of objects on this file.
Definition TFile.cxx:1183
virtual TKey * CreateKey(TDirectory *mother, const TObject *obj, const char *name, Int_t bufsize)
Creates key for object and converts data to buffer.
Definition TFile.cxx:1047
virtual Long64_t GetSize() const
Returns the current file size.
Definition TFile.cxx:1347
virtual Long64_t GetEND() const
Definition TFile.h:231
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition TFile.cxx:2417
static TFile *& CurrentFile()
Return the current ROOT file if any.
Definition TFile.cxx:1067
virtual const TUrl * GetEndpointUrl() const
Definition TFile.h:235
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4089
@ kReproducible
Definition TFile.h:197
@ kWriteError
Definition TFile.h:194
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition TFile.cxx:1770
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition THashList.h:34
void Reset()
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
void Delete(Option_t *option="") override
Delete an object from the file.
Definition TKey.cxx:539
virtual Long64_t GetSeekKey() const
Definition TKey.h:89
Int_t Sizeof() const override
Return the size in bytes of the key header structure.
Definition TKey.cxx:1342
Int_t GetKeylen() const
Definition TKey.h:84
Int_t GetObjlen() const
Definition TKey.h:87
Int_t GetNbytes() const
Definition TKey.h:86
Short_t GetKeep() const
Returns the "KEEP" status.
Definition TKey.cxx:594
virtual const char * GetClassName() const
Definition TKey.h:75
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition TKey.cxx:1274
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1231
virtual Long64_t GetSeekPdir() const
Definition TKey.h:90
void SetMotherDir(TDirectory *dir)
Definition TKey.h:112
virtual void ls(Bool_t current) const
List Key contents.
Definition TKey.cxx:695
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:578
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:759
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1456
virtual char * GetBuffer() const
Definition TKey.h:78
void FillBuffer(char *&buffer) override
Encode key header into output buffer.
Definition TKey.cxx:602
A doubly linked list.
Definition TList.h:38
TObject * Before(const TObject *obj) const override
Returns the object before object obj.
Definition TList.cxx:369
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:657
void AddBefore(const TObject *before, TObject *obj) override
Insert object before object before in the list.
Definition TList.cxx:194
virtual TObjLink * FirstLink() const
Definition TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
This class implements a shared memory region mapped to a file.
Definition TMapFile.h:26
static TClass * Class()
void Add(const TObject *obj, const char *name="")
Add an object to the list of objects to be stored in shared memory.
Definition TMapFile.cxx:611
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
TClass * IsA() const override
Definition TNamed.h:58
Mother of all ROOT objects.
Definition TObject.h:41
virtual Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition TObject.cxx:572
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:906
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:420
static TClass * Class()
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:898
@ kOnlyPrepStep
Used to request that the class specific implementation of TObject::Write just prepare the objects to ...
Definition TObject.h:106
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:266
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:798
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:542
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1005
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1033
virtual TClass * IsA() const
Definition TObject.h:243
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition TObject.cxx:591
void ResetBit(UInt_t f)
Definition TObject.h:198
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:65
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:979
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:2887
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2895
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2746
Regular expression class.
Definition TRegexp.h:31
Int_t GetOffset() const
virtual Int_t GetExecID() const
Returns the TExec id for the EXEC instruction in the comment field of a TRef data member.
Describes a persistent version of a class.
TObjArray * GetElements() const override
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
const char * Data() const
Definition TString.h:376
@ kBoth
Definition TString.h:276
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
Bool_t IsNull() const
Definition TString.h:414
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1412
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1296
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition TUUID.h:42
virtual void Streamer(TBuffer &)
const char * AsString() const
Return UUID as string. Copy string immediately since it will be reused.
Definition TUUID.cxx:571
Int_t Sizeof() const
Definition TUUID.h:85
void FillBuffer(char *&buffer)
Stream UUID into output buffer.
Definition TUUID.cxx:275
void StreamerV1(TBuffer &b)
Stream UUID from input buffer.
Definition TUUID.cxx:309
Abstract Interface class describing Streamer information for one class.
virtual TClass * GetClass() const =0
const Int_t n
Definition legend1.C:16
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition Rtypes.h:119
TCanvas * slash()
Definition slash.C:1