Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TKey.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Rene Brun 28/12/94
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, 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 TKey
14\ingroup IO
15
16 Book space in a file, create I/O buffers, to fill them, (un)compress them.
17
18 The TKey class includes functions to book space in a file, to create I/O
19 buffers, to fill these buffers, to compress/uncompress data buffers.
20 Before saving (making persistent) an object in a file, a key must
21 be created. The key structure contains all the information to
22 uniquely identify a persistent object in a file.
23 | Data Member | Explanation |
24 |-------------|-------------|
25 | fNbytes | Number of bytes for the compressed object and key. |
26 | fObjlen | Length of uncompressed object. |
27 | fDatime | Date/Time when the object was written. |
28 | fKeylen | Number of bytes for the key structure. |
29 | fCycle | Cycle number of the object. |
30 | fSeekKey | Address of the object on file (points to fNbytes). This is a redundant information used to cross-check the data base integrity. |
31 | fSeekPdir | Pointer to the directory supporting this object.|
32 | fClassName | Object class name. |
33 | fName | Name of the object. |
34 | fTitle | Title of the object. |
35
36 In the 16 highest bits of fSeekPdir is encoded a pid offset. This
37 offset is to be added to the pid index stored in the TRef object
38 and the referenced TObject.
39
40 The TKey class is used by ROOT to:
41 - Write an object in the current directory
42 - Write a new ntuple buffer
43
44 The structure of a file is shown in TFile::TFile.
45 The structure of a directory is shown in TDirectoryFile::TDirectoryFile.
46 The TKey class is used by the TBasket class.
47 See also TTree.
48*/
49
50#include <atomic>
51#include <iostream>
52
53#include "TROOT.h"
54#include "TClass.h"
55#include "TDirectoryFile.h"
56#include "TFile.h"
57#include "TKey.h"
58#include "TBufferFile.h"
59#include "TFree.h"
60#include "TBrowser.h"
61#include "Bytes.h"
62#include "TInterpreter.h"
63#include "TError.h"
65#include "TSchemaRuleSet.h"
66#include "ThreadLocalStorage.h"
67
68#include "RZip.h"
69
70const Int_t kTitleMax = 32000;
71
72#if !defined(_MSC_VER) || (_MSC_VER>1300)
73const ULong64_t kPidOffsetMask = 0xffffffffffffULL;
74#else
75const ULong64_t kPidOffsetMask = 0xffffffffffffUL;
76#endif
78
79const static TString gTDirectoryString("TDirectory");
80std::atomic<UInt_t> keyAbsNumber{0};
81
82
83////////////////////////////////////////////////////////////////////////////////
84/// TKey default constructor.
85
86TKey::TKey() : TNamed(), fDatime((UInt_t)0)
87{
88 Build(0, "", 0);
89
90 fKeylen = Sizeof();
91
93}
94
95////////////////////////////////////////////////////////////////////////////////
96/// TKey default constructor.
99{
100 Build(motherDir, "", 0);
101
102 fKeylen = Sizeof();
103
105}
106
107////////////////////////////////////////////////////////////////////////////////
108/// Copy a TKey from its original directory to the new 'motherDir'
109
111{
113
114 fPidOffset = orig.fPidOffset + pidOffset;
115 fNbytes = orig.fNbytes;
116 fObjlen = orig.fObjlen;
117 fClassName = orig.fClassName;
118 fName = orig.fName;
119 fTitle = orig.fTitle;
120
121 fCycle = fMotherDir->AppendKey(this);
122 fSeekPdir = 0;
123 fSeekKey = 0;
124 fLeft = 0;
125
129
130 fKeylen = Sizeof(); // fVersion must be set.
131
134 UInt_t alloc = fNbytes + sizeof(Int_t); // The extra Int_t is for any free space information.
135 if (fKeylen < orig.fKeylen) {
136 bufferDecOffset = orig.fKeylen - fKeylen;
138 } else if (fKeylen > orig.fKeylen) {
139 bufferIncOffset = fKeylen - orig.fKeylen;
142 }
143
146
147 // Steal the data from the old key.
148
149 TFile* f = orig.GetFile();
150 if (f) {
151 Int_t nsize = orig.fNbytes;
152 f->Seek(orig.fSeekKey);
153 if( f->ReadBuffer(fBuffer+bufferIncOffset,nsize) )
154 {
155 Error("ReadFile", "Failed to read data.");
156 return;
157 }
158 if (gDebug) {
159 std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
160 }
161 }
162 fBuffer += bufferDecOffset; // Reset the buffer to be appropriate for this key.
164 Create(nout);
166 Streamer(*fBufferRef); //write key itself again
167}
168
169////////////////////////////////////////////////////////////////////////////////
170/// Create a TKey object to read keys.
171/// Constructor called by TDirectoryFile::ReadKeys and by TFile::TFile.
172/// A TKey object is created to read the keys structure itself.
173
175{
176 Build(motherDir, "", pointer);
177
178 fSeekKey = pointer;
179 fNbytes = nbytes;
180 fBuffer = new char[nbytes];
182}
183
184////////////////////////////////////////////////////////////////////////////////
185/// Create a TKey object with the specified name, title for the given class.
186///
187/// WARNING: in name avoid special characters like '^','$','.' that are used
188/// by the regular expression parser (see TRegexp).
189
190TKey::TKey(const char *name, const char *title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
191 : TNamed(name,title)
192{
193 Build(motherDir, cl->GetName(), -1);
194
195 fKeylen = Sizeof();
196 fObjlen = nbytes;
197 Create(nbytes);
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Create a TKey object with the specified name, title for the given class.
202///
203/// WARNING: in name avoid special characters like '^','$','.' that are used
204/// by the regular expression parser (see TRegexp).
205
207 : TNamed(name,title)
208{
209 Build(motherDir, cl->GetName(), -1);
210
211 fKeylen = Sizeof();
212 fObjlen = nbytes;
213 Create(nbytes);
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Create a TKey object for a TObject* and fill output buffer
218///
219/// WARNING: in name avoid special characters like '^','$','.' that are used
220/// by the regular expression parser (see TRegexp).
221
223 : TNamed(name, obj->GetTitle())
224{
225 R__ASSERT(obj);
226
227 if (!obj->IsA()->HasDefaultConstructor()) {
228 Warning("TKey", "since %s has no public constructor\n"
229 "\twhich can be called without argument, objects of this class\n"
230 "\tcan not be read with the current library. You will need to\n"
231 "\tadd a default constructor before attempting to read it.",
232 obj->ClassName());
233 }
234
235 Build(motherDir, obj->ClassName(), -1);
236
237 Int_t lbuf, nout, noutot, bufmax, nzip;
240 fCycle = fMotherDir->AppendKey(this);
241
242 Streamer(*fBufferRef); //write key itself
244 fBufferRef->MapObject(obj); //register obj in map in case of self reference
245 ((TObject*)obj)->Streamer(*fBufferRef); //write object
247 fObjlen = lbuf - fKeylen;
248
251 if (cxlevel > 0 && fObjlen > 256) {
252 Int_t nbuffers = 1 + (fObjlen - 1)/kMAXZIPBUF;
253 Int_t buflen = std::max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
254 fBuffer = new char[buflen];
255 char *objbuf = fBufferRef->Buffer() + fKeylen;
256 char *bufcur = &fBuffer[fKeylen];
257 noutot = 0;
258 nzip = 0;
259 for (Int_t i = 0; i < nbuffers; ++i) {
260 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
261 else bufmax = kMAXZIPBUF;
263 if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
264 delete[] fBuffer;
265 bufcur = nullptr;
269 Streamer(*fBufferRef); //write key itself again
270 return;
271 }
272 bufcur += nout;
273 noutot += nout;
275 nzip += kMAXZIPBUF;
276 }
277 Create(noutot);
279 Streamer(*fBufferRef); //write key itself again
281 delete fBufferRef; fBufferRef = 0;
282 } else {
286 Streamer(*fBufferRef); //write key itself again
287 }
288}
289
290////////////////////////////////////////////////////////////////////////////////
291/// Create a TKey object for any object obj of class cl d and fill
292/// output buffer.
293///
294/// WARNING: in name avoid special characters like '^','$','.' that are used
295/// by the regular expression parser (see TRegexp).
296
297TKey::TKey(const void *obj, const TClass *cl, const char *name, Int_t bufsize, TDirectory *motherDir) : TNamed(name, "")
298{
299 R__ASSERT(obj && cl);
300
301 if (!cl->HasDefaultConstructor()) {
302 Warning("TKey", "since %s has no public constructor\n"
303 "\twhich can be called without argument, objects of this class\n"
304 "\tcan not be read with the current library. You will need to\n"
305 "\tadd a default constructor before attempting to read it.",
306 cl->GetName());
307 }
308
309 TClass *clActual = cl->GetActualClass(obj);
310 const void* actualStart;
311 if (clActual) {
312 const char *temp = (const char*) obj;
313 // clActual->GetStreamerInfo();
314 Int_t offset = (cl != clActual) ?
315 clActual->GetBaseClassOffset(cl) : 0;
316 temp -= offset;
317 actualStart = temp;
318 } else {
319 // We could not determine the real type of this object,
320 // let's assume it is the one given by the caller.
321 clActual = const_cast<TClass*>(cl);
322 actualStart = obj;
323 }
324
325 Build(motherDir, clActual->GetName(), -1);
326
329
330 Streamer(*fBufferRef); //write key itself
332
333 Int_t lbuf, nout, noutot, bufmax, nzip;
334
335 fBufferRef->MapObject(actualStart,clActual); //register obj in map in case of self reference
336 clActual->Streamer((void*)actualStart, *fBufferRef); //write object
338 fObjlen = lbuf - fKeylen;
339
340 // Append to mother directory only after the call to Streamer() was
341 // successful (and didn't throw).
342 fCycle = fMotherDir->AppendKey(this);
343
346 if (cxlevel > 0 && fObjlen > 256) {
347 Int_t nbuffers = 1 + (fObjlen - 1)/kMAXZIPBUF;
348 Int_t buflen = std::max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
349 fBuffer = new char[buflen];
350 char *objbuf = fBufferRef->Buffer() + fKeylen;
351 char *bufcur = &fBuffer[fKeylen];
352 noutot = 0;
353 nzip = 0;
354 for (Int_t i = 0; i < nbuffers; ++i) {
355 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
356 else bufmax = kMAXZIPBUF;
358 if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
359 delete[] fBuffer;
360 bufcur = nullptr;
364 Streamer(*fBufferRef); //write key itself again
365 return;
366 }
367 bufcur += nout;
368 noutot += nout;
370 nzip += kMAXZIPBUF;
371 }
372 Create(noutot);
374 Streamer(*fBufferRef); //write key itself again
376 delete fBufferRef; fBufferRef = 0;
377 } else {
381 Streamer(*fBufferRef); //write key itself again
382 }
383}
384
385////////////////////////////////////////////////////////////////////////////////
386/// Method used in all TKey constructor to initialize basic data fields.
387///
388/// The member filepos is used to calculate correct version number of key
389/// if filepos==-1, end of file position is used.
390
391void TKey::Build(TDirectory* motherDir, const char* classname, Long64_t filepos)
392{
394
395 fPidOffset = 0;
396 fNbytes = 0;
397 fBuffer = 0;
398 fKeylen = 0;
399 fObjlen = 0;
400 fBufferRef = 0;
401 fCycle = 0;
402 fSeekPdir = 0;
403 fSeekKey = 0;
404 fLeft = 0;
405
406 fClassName = classname;
407 //the following test required for forward and backward compatibility
408 if (fClassName == "TDirectoryFile") SetBit(kIsDirectoryFile);
409
411
412 if ((filepos==-1) && GetFile()) filepos = GetFile()->GetEND();
414
416
419}
420
421////////////////////////////////////////////////////////////////////////////////
422/// Read object from disk and call its Browse() method.
423///
424/// If object with same name already exist in memory delete it (like
425/// TDirectoryFile::Get() is doing), except when the key references a
426/// folder in which case we don't want to re-read the folder object
427/// since it might contain new objects not yet saved.
428
430{
431 if (fMotherDir==0) return;
432
434
435 void* obj = fMotherDir->GetList()->FindObject(GetName());
436 if (obj && objcl->IsTObject()) {
437 TObject *tobj = (TObject*) objcl->DynamicCast(TObject::Class(), obj);
438 if (!tobj->IsFolder()) {
439 if (tobj->InheritsFrom(TCollection::Class()))
440 tobj->Delete(); // delete also collection elements
441 delete tobj;
442 obj = 0;
443 }
444 }
445
446 if (!obj)
447 obj = ReadObj();
448
449 if (b && obj) {
450 objcl->Browse(obj,b);
451 b->SetRefreshFlag(kTRUE);
452 }
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Create a TKey object of specified size.
457///
458/// If externFile!=0, key will be allocated in specified file, otherwise file
459/// of mother directory will be used.
460
462{
464
465 TFile *f = externFile;
466 if (!f) f = GetFile();
467 if (!f) {
468 Error("Create","Cannot create key without file");
469 return;
470 }
471
473 TList *lfree = f->GetListOfFree();
474 TFree *f1 = (TFree*)lfree->First();
475//*-*-------------------find free segment
476//*-* =================
477 TFree *bestfree = f1->GetBestFree(lfree,nsize);
478 if (bestfree == 0) {
479 Error("Create","Cannot allocate %d bytes for ID = %s Title = %s",
481 return;
482 }
483
484 if (f->TestBit(TFile::kReproducible))
486
487 fDatime.Set();
488 fSeekKey = bestfree->GetFirst();
489//*-*----------------- Case Add at the end of the file
490 if (fSeekKey >= f->GetEND()) {
491 f->SetEND(fSeekKey+nsize);
492 bestfree->SetFirst(fSeekKey+nsize);
493 if (f->GetEND() > bestfree->GetLast()) {
494 bestfree->SetLast(bestfree->GetLast() + 1000000000);
495 }
496 fLeft = -1;
497 if (!fBuffer) fBuffer = new char[nsize];
498 } else {
499 fLeft = Int_t(bestfree->GetLast() - fSeekKey - nsize + 1);
500 }
501//*-*----------------- Case where new object fills exactly a deleted gap
502 fNbytes = nsize;
503 if (fLeft == 0) {
504 if (!fBuffer) {
505 fBuffer = new char[nsize];
506 }
507 lfree->Remove(bestfree);
508 delete bestfree;
509 }
510//*-*----------------- Case where new object is placed in a deleted gap larger than itself
511 if (fLeft > 0) { // found a bigger segment
512 if (!fBuffer) {
513 fBuffer = new char[nsize+sizeof(Int_t)];
514 }
515 char *buffer = fBuffer+nsize;
516 Int_t nbytesleft = -fLeft; // set header of remaining record
517 tobuf(buffer, nbytesleft);
518 bestfree->SetFirst(fSeekKey+nsize);
519 }
520
521 fSeekPdir = externFile ? externFile->GetSeekDir() : fMotherDir->GetSeekDir();
522}
523
524////////////////////////////////////////////////////////////////////////////////
525/// TKey default destructor.
526
528{
530 fMotherDir->GetListOfKeys()->Remove(this);
532}
533
534////////////////////////////////////////////////////////////////////////////////
535/// Delete an object from the file.
536///
537/// Note: the key is not deleted. You still have to call "delete key".
538/// This is different from the behaviour of TObject::Delete()!
539
541{
543 // TDirectoryFile assumes that its location on file never change (for example updates are partial)
544 // and never checks if the space might have been released and thus over-write any data that might
545 // have been written there.
546 if (option && option[0] == 'v')
547 printf("Rejected attempt to delete TDirectoryFile key: %s at address %lld, nbytes = %d\n",
549 return;
550 }
551 if (option && option[0] == 'v') printf("Deleting key: %s at address %lld, nbytes = %d\n",GetName(),fSeekKey,fNbytes);
552 Long64_t first = fSeekKey;
553 Long64_t last = fSeekKey + fNbytes -1;
554 if (GetFile()) GetFile()->MakeFree(first, last); // release space used by this key
555 fMotherDir->GetListOfKeys()->Remove(this);
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Delete key buffer(s).
560
562{
563 if (fBufferRef) {
564 delete fBufferRef;
565 fBufferRef = 0;
566 } else {
567 // We only need to delete fBuffer if fBufferRef is zero because
568 // if fBufferRef exists, we delegate ownership of fBuffer to fBufferRef.
569 if (fBuffer) {
570 delete [] fBuffer;
571 }
572 }
573 fBuffer = 0;
574}
575
576////////////////////////////////////////////////////////////////////////////////
577/// Return cycle number associated to this key.
578
580{
581 return ((fCycle >0) ? fCycle : -fCycle);
582}
583
584////////////////////////////////////////////////////////////////////////////////
585/// Returns file to which key belong.
586
588{
589 return fMotherDir!=0 ? fMotherDir->GetFile() : gFile;
590}
591
592////////////////////////////////////////////////////////////////////////////////
593/// Returns the "KEEP" status.
594
596{
597 return ((fCycle >0) ? 0 : 1);
598}
599
600////////////////////////////////////////////////////////////////////////////////
601/// Encode key header into output buffer.
602
603void TKey::FillBuffer(char *&buffer)
604{
605 tobuf(buffer, fNbytes);
607 tobuf(buffer, version);
608
609 tobuf(buffer, fObjlen);
611 TDatime((UInt_t) 1).FillBuffer(buffer);
612 else
613 fDatime.FillBuffer(buffer);
614 tobuf(buffer, fKeylen);
615 tobuf(buffer, fCycle);
616 if (fVersion > 1000) {
617 tobuf(buffer, fSeekKey);
618
619 // We currently store in the 16 highest bit of fSeekPdir the value of
620 // fPidOffset. This offset is used when a key (or basket) is transfered from one
621 // file to the other. In this case the TRef and TObject might have stored a
622 // pid index (to retrieve TProcessIDs) which refered to their order on the original
623 // file, the fPidOffset is to be added to those values to correctly find the
624 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
625 // and need to be zero for new key/basket.
627 tobuf(buffer, pdir);
628 } else {
629 tobuf(buffer, (Int_t)fSeekKey);
630 tobuf(buffer, (Int_t)fSeekPdir);
631 }
633 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
634 gTDirectoryString.FillBuffer(buffer);
635 } else {
636 fClassName.FillBuffer(buffer);
637 }
638 fName.FillBuffer(buffer);
639 fTitle.FillBuffer(buffer);
640}
641
642////////////////////////////////////////////////////////////////////////////////
643/// Increment fPidOffset by 'offset'.
644///
645/// This offset is used when a key (or basket) is transfered from one file to
646/// the other. In this case the TRef and TObject might have stored a pid
647/// index (to retrieve TProcessIDs) which refered to their order on the
648/// original file, the fPidOffset is to be added to those values to correctly
649/// find the TProcessID. This fPidOffset needs to be increment if the
650/// key/basket is copied and need to be zero for new key/basket.
651
653{
655 if (fPidOffset) {
656 // We currently store fPidOffset in the 16 highest bit of fSeekPdir, which
657 // need to be store as a 64 bit integer. So we require this key to be
658 // a 'large file' key.
659 if (fVersion<1000) fVersion += 1000;
660 }
661}
662
663////////////////////////////////////////////////////////////////////////////////
664/// Check if object referenced by the key is a folder.
665
667{
668 Bool_t ret = kFALSE;
669
670 TClass *classPtr = TClass::GetClass((const char *) fClassName);
671 if (classPtr && classPtr->GetState() > TClass::kEmulated && classPtr->IsTObject()) {
672 TObject *obj = (TObject *) classPtr->DynamicCast(TObject::Class(), classPtr->New(TClass::kDummyNew));
673 if (obj) {
674 ret = obj->IsFolder();
675 delete obj;
676 }
677 }
678
679 return ret;
680}
681
682////////////////////////////////////////////////////////////////////////////////
683/// Set the "KEEP" status.
684///
685/// When the KEEP flag is set to 1 the object cannot be purged.
686
688{
689 if (fCycle >0) fCycle = -fCycle;
690}
691
692////////////////////////////////////////////////////////////////////////////////
693/// List Key contents.
694/// Add indicator of whether it is the current item or a backup copy.
695
696void TKey::ls(Bool_t current) const
697{
699 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle();
700 std::cout << (current ? " [current cycle]" : " [backup cycle]");
701 std::cout <<std::endl;
702}
703
704////////////////////////////////////////////////////////////////////////////////
705/// List Key contents.
706
707void TKey::ls(Option_t *) const
708{
710 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<std::endl;
711}
712
713////////////////////////////////////////////////////////////////////////////////
714/// Print key contents.
715
717{
718 printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle());
719}
720
721////////////////////////////////////////////////////////////////////////////////
722/// To read a TObject* from the file.
723///
724/// The object associated to this key is read from the file into memory
725/// Once the key structure is read (via Streamer) the class identifier
726/// of the object is known.
727/// Using the class identifier we find the TClass object for this class.
728/// A TClass object contains a full description (i.e. dictionary) of the
729/// associated class. In particular the TClass object can create a new
730/// object of the class type it describes. This new object now calls its
731/// Streamer function to rebuilt itself.
732///
733/// Use TKey::ReadObjectAny to read any object non-derived from TObject
734///
735/// ### Note
736/// A C style cast can only be used in the case where the final class
737/// of this object derives from TObject as a first inheritance, otherwise
738/// one must use a dynamic_cast.
739///
740/// #### Example1: simplified case
741/// ~~~{.cpp}
742/// class MyClass : public TObject, public AnotherClass
743/// ~~~
744/// then on return, one get away with using:
745/// ~~~{.cpp}
746/// MyClass *obj = (MyClass*)key->ReadObj();
747/// ~~~
748///
749/// #### Example2: Usual case (recommended unless performance is critical)
750/// ~~~{.cpp}
751/// MyClass *obj = dynamic_cast<MyClass*>(key->ReadObj());
752/// ~~~
753/// which support also the more complex inheritance like:
754/// ~~~{.cpp}
755/// class MyClass : public AnotherClass, public TObject
756/// ~~~
757///
758/// Of course, `dynamic_cast<>` can also be used in the example 1.
759
761{
763 if (!cl) {
764 Error("ReadObj", "Unknown class %s", fClassName.Data());
765 return 0;
766 }
767 if (!cl->IsTObject()) {
768 // in principle user should call TKey::ReadObjectAny!
769 return (TObject*)ReadObjectAny(0);
770 }
771
773 if (!bufferRef.Buffer()) {
774 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
775 return 0;
776 }
777 if (GetFile()==0) return 0;
778 bufferRef.SetParent(GetFile());
779 bufferRef.SetPidOffset(fPidOffset);
780
781 std::unique_ptr<char []> compressedBuffer;
782 auto storeBuffer = fBuffer;
783 if (fObjlen > fNbytes-fKeylen) {
784 compressedBuffer.reset(new char[fNbytes]);
786 if( !ReadFile() ) //Read object structure from file
787 {
788 fBuffer = 0;
789 return 0;
790 }
792 } else {
793 fBuffer = bufferRef.Buffer();
794 if( !ReadFile() ) { //Read object structure from file
795
796 fBuffer = 0;
797 return 0;
798 }
799 }
801
802 // get version of key
803 bufferRef.SetBufferOffset(sizeof(fNbytes));
804 Version_t kvers = bufferRef.ReadVersion();
805
806 bufferRef.SetBufferOffset(fKeylen);
807 TObject *tobj = 0;
808 // Create an instance of this class
809
810 char *pobj = (char*)cl->New();
811 if (!pobj) {
812 Error("ReadObj", "Cannot create new object of class %s", fClassName.Data());
813 return 0;
814 }
816 if (baseOffset==-1) {
817 // cl does not inherit from TObject.
818 // Since this is not possible yet, the only reason we could reach this code
819 // is because something is screw up in the ROOT code.
820 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
821 fClassName.Data());
822 }
824 if (kvers > 1)
825 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
826
827 if (fObjlen > fNbytes-fKeylen) {
828 char *objbuf = bufferRef.Buffer() + fKeylen;
830 Int_t nin, nout = 0, nbuf;
831 Int_t noutot = 0;
832 while (1) {
834 if (hc!=0) break;
835 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
836 if (!nout) break;
837 noutot += nout;
838 if (noutot >= fObjlen) break;
839 bufcur += nin;
840 objbuf += nout;
841 }
842 compressedBuffer.reset(nullptr);
843 if (nout) {
844 tobj->Streamer(bufferRef); //does not work with example 2 above
845 } else {
846 // Even-though we have a TObject, if the class is emulated the virtual
847 // table may not be 'right', so let's go via the TClass.
848 cl->Destructor(pobj);
849 return nullptr;
850 }
851 } else {
852 tobj->Streamer(bufferRef);
853 }
854
855 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
856
858 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
859 dir->SetName(GetName());
860 dir->SetTitle(GetTitle());
861 dir->SetMother(fMotherDir);
862 fMotherDir->Append(dir);
863 }
864
865 // Append the object to the directory if requested:
866 {
868 if (addfunc) {
869 addfunc(pobj, fMotherDir);
870 }
871 }
872
873 return tobj;
874}
875
876////////////////////////////////////////////////////////////////////////////////
877/// To read a TObject* from bufferRead.
878///
879/// This function is identical to TKey::ReadObj, but it reads directly from
880/// bufferRead instead of reading from a file.
881/// The object associated to this key is read from the buffer into memory
882/// Using the class identifier we find the TClass object for this class.
883/// A TClass object contains a full description (i.e. dictionary) of the
884/// associated class. In particular the TClass object can create a new
885/// object of the class type it describes. This new object now calls its
886/// Streamer function to rebuilt itself.
887///
888/// ### Note
889/// This function is called only internally by ROOT classes.
890/// Although being public it is not supposed to be used outside ROOT.
891/// If used, you must make sure that the bufferRead is large enough to
892/// accomodate the object being read.
893
895{
896
898 if (!cl) {
899 Error("ReadObjWithBuffer", "Unknown class %s", fClassName.Data());
900 return 0;
901 }
902 if (!cl->IsTObject()) {
903 // in principle user should call TKey::ReadObjectAny!
904 return (TObject*)ReadObjectAny(0);
905 }
906
908 if (!bufferRef.Buffer()) {
909 Error("ReadObjWithBuffer", "Cannot allocate buffer: fObjlen = %d", fObjlen);
910 return 0;
911 }
912 if (GetFile()==0) return 0;
913 bufferRef.SetParent(GetFile());
914 bufferRef.SetPidOffset(fPidOffset);
915
916 auto storeBuffer = fBuffer;
917 if (fObjlen > fNbytes-fKeylen) {
920 } else {
921 fBuffer = bufferRef.Buffer();
922 ReadFile(); //Read object structure from file
923 }
925
926 // get version of key
927 bufferRef.SetBufferOffset(sizeof(fNbytes));
928 Version_t kvers = bufferRef.ReadVersion();
929
930 bufferRef.SetBufferOffset(fKeylen);
931 TObject *tobj = 0;
932 // Create an instance of this class
933
934 char *pobj = (char*)cl->New();
935 if (!pobj) {
936 Error("ReadObjWithBuffer", "Cannot create new object of class %s", fClassName.Data());
937 return 0;
938 }
940 if (baseOffset==-1) {
941 // cl does not inherit from TObject.
942 // Since this is not possible yet, the only reason we could reach this code
943 // is because something is screw up in the ROOT code.
944 Fatal("ReadObjWithBuffer","Incorrect detection of the inheritance from TObject for class %s.\n",
945 fClassName.Data());
946 }
948
949 if (kvers > 1)
950 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
951
952 if (fObjlen > fNbytes-fKeylen) {
953 char *objbuf = bufferRef.Buffer() + fKeylen;
955 Int_t nin, nout = 0, nbuf;
956 Int_t noutot = 0;
957 while (1) {
959 if (hc!=0) break;
960 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
961 if (!nout) break;
962 noutot += nout;
963 if (noutot >= fObjlen) break;
964 bufcur += nin;
965 objbuf += nout;
966 }
967 if (nout) {
968 tobj->Streamer(bufferRef); //does not work with example 2 above
969 } else {
970 // Even-though we have a TObject, if the class is emulated the virtual
971 // table may not be 'right', so let's go via the TClass.
972 cl->Destructor(pobj);
973 return nullptr;
974 }
975 } else {
976 tobj->Streamer(bufferRef);
977 }
978
979 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
980
982 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
983 dir->SetName(GetName());
984 dir->SetTitle(GetTitle());
985 dir->SetMother(fMotherDir);
986 fMotherDir->Append(dir);
987 }
988
989 // Append the object to the directory if requested:
990 {
992 if (addfunc) {
993 addfunc(pobj, fMotherDir);
994 }
995 }
996
997 return tobj;
998}
999
1000////////////////////////////////////////////////////////////////////////////////
1001/// To read an object (non deriving from TObject) from the file.
1002///
1003/// If expectedClass is not null, we checked that that actual class of the
1004/// object stored is suitable to be stored in a pointer pointing to an object
1005/// of class 'expectedClass'. We also adjust the value of the returned address
1006/// so that it is suitable to be cast (C-Style)
1007/// a pointer pointing to an object of class 'expectedClass'.
1008///
1009/// So for example if the class Bottom inherits from Top and the object
1010/// stored is of type Bottom you can safely do:
1011/// ~~~{.cpp}
1012/// auto TopClass = TClass::GetClass("Top");
1013/// auto ptr = (Top*) key->ReadObjectAny( TopClass );
1014/// if (ptr==0) printError("the object stored in the key is not of the expected type\n");
1015/// ~~~
1016/// The object associated to this key is read from the file into memory.
1017/// Once the key structure is read (via Streamer) the class identifier
1018/// of the object is known.
1019/// Using the class identifier we find the TClass object for this class.
1020/// A TClass object contains a full description (i.e. dictionary) of the
1021/// associated class. In particular the TClass object can create a new
1022/// object of the class type it describes. This new object now calls its
1023/// Streamer function to rebuilt itself.
1024
1026{
1028 if (!bufferRef.Buffer()) {
1029 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
1030 return 0;
1031 }
1032 if (GetFile()==0) return 0;
1033 bufferRef.SetParent(GetFile());
1034 bufferRef.SetPidOffset(fPidOffset);
1035
1036 std::unique_ptr<char []> compressedBuffer;
1037 auto storeBuffer = fBuffer;
1038 if (fObjlen > fNbytes-fKeylen) {
1039 compressedBuffer.reset(new char[fNbytes]);
1040 fBuffer = compressedBuffer.get();
1041 ReadFile(); //Read object structure from file
1042 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1043 } else {
1044 fBuffer = bufferRef.Buffer();
1045 ReadFile(); //Read object structure from file
1046 }
1048
1049 // get version of key
1050 bufferRef.SetBufferOffset(sizeof(fNbytes));
1051 Version_t kvers = bufferRef.ReadVersion();
1052
1053 bufferRef.SetBufferOffset(fKeylen);
1055 TClass *clOnfile = 0;
1056 if (!cl) {
1057 Error("ReadObjectAny", "Unknown class %s", fClassName.Data());
1058 return 0;
1059 }
1060 Int_t baseOffset = 0;
1061 if (expectedClass) {
1062 // baseOffset will be -1 if cl does not inherit from expectedClass
1064 if (baseOffset == -1) {
1065 // The 2 classes are unrelated, maybe there is a converter between the 2.
1066
1067 if (!expectedClass->GetSchemaRules() ||
1068 !expectedClass->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()))
1069 {
1070 // There is no converter
1071 return 0;
1072 }
1073 baseOffset = 0; // For now we do not support requesting from a class that is the base of one of the class for which there is transformation to ....
1074 clOnfile = cl;
1075 cl = const_cast<TClass*>(expectedClass);
1076 if (gDebug > 0)
1077 Info("ReadObjectAny", "Using Converter StreamerInfo from %s to %s", clOnfile->GetName(),
1078 expectedClass->GetName());
1079 }
1080 if (cl->GetState() > TClass::kEmulated && expectedClass->GetState() <= TClass::kEmulated) {
1081 //we cannot mix a compiled class with an emulated class in the inheritance
1082 Warning("ReadObjectAny",
1083 "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
1084 cl->GetName(),expectedClass->GetName());
1085 }
1086 }
1087 // Create an instance of this class
1088
1089 void *pobj = cl->New();
1090 if (!pobj) {
1091 Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data());
1092 return 0;
1093 }
1094
1095 if (kvers > 1)
1096 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
1097
1098 if (fObjlen > fNbytes-fKeylen) {
1099 char *objbuf = bufferRef.Buffer() + fKeylen;
1101 Int_t nin, nout = 0, nbuf;
1102 Int_t noutot = 0;
1103 while (1) {
1105 if (hc!=0) break;
1106 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1107 if (!nout) break;
1108 noutot += nout;
1109 if (noutot >= fObjlen) break;
1110 bufcur += nin;
1111 objbuf += nout;
1112 }
1113 if (nout) {
1114 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1115 } else {
1116 cl->Destructor(pobj);
1117 return nullptr;
1118 }
1119 } else {
1120 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1121 }
1122
1123 if (cl->IsTObject()) {
1125 if (tobjBaseOffset == -1) {
1126 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
1127 fClassName.Data());
1128 }
1129 TObject *tobj = (TObject*)( ((char*)pobj) + tobjBaseOffset);
1130
1131 // See similar adjustments in ReadObj
1132 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
1133
1135 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1136 dir->SetName(GetName());
1137 dir->SetTitle(GetTitle());
1138 dir->SetMother(fMotherDir);
1139 fMotherDir->Append(dir);
1140 }
1141 }
1142
1143 {
1144 // Append the object to the directory if requested:
1146 if (addfunc) {
1147 addfunc(pobj, fMotherDir);
1148 }
1149 }
1150
1151 return ( ((char*)pobj) + baseOffset );
1152}
1153
1154////////////////////////////////////////////////////////////////////////////////
1155/// To read an object from the file.
1156///
1157/// The object associated to this key is read from the file into memory.
1158/// Before invoking this function, obj has been created via the
1159/// default constructor.
1160
1162{
1163 if (!obj || (GetFile()==0)) return 0;
1164
1166 bufferRef.SetParent(GetFile());
1167 bufferRef.SetPidOffset(fPidOffset);
1168
1169 if (fVersion > 1)
1170 bufferRef.MapObject(obj); //register obj in map to handle self reference
1171
1172 std::unique_ptr<char []> compressedBuffer;
1173 auto storeBuffer = fBuffer;
1174 if (fObjlen > fNbytes-fKeylen) {
1175 compressedBuffer.reset(new char[fNbytes]);
1176 fBuffer = compressedBuffer.get();
1177 ReadFile(); //Read object structure from file
1178 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1179 } else {
1180 fBuffer = bufferRef.Buffer();
1181 ReadFile(); //Read object structure from file
1182 }
1184
1185 bufferRef.SetBufferOffset(fKeylen);
1186 if (fObjlen > fNbytes-fKeylen) {
1187 char *objbuf = bufferRef.Buffer() + fKeylen;
1189 Int_t nin, nout = 0, nbuf;
1190 Int_t noutot = 0;
1191 while (1) {
1193 if (hc!=0) break;
1194 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1195 if (!nout) break;
1196 noutot += nout;
1197 if (noutot >= fObjlen) break;
1198 bufcur += nin;
1199 objbuf += nout;
1200 }
1201 if (nout) obj->Streamer(bufferRef);
1202 } else {
1203 obj->Streamer(bufferRef);
1204 }
1205
1206 // Append the object to the directory if requested:
1207 {
1208 ROOT::DirAutoAdd_t addfunc = obj->IsA()->GetDirectoryAutoAdd();
1209 if (addfunc) {
1210 addfunc(obj, fMotherDir);
1211 }
1212 }
1213
1214 return fNbytes;
1215}
1216
1217////////////////////////////////////////////////////////////////////////////////
1218/// Decode input buffer.
1219///
1220/// In some situation will add key to gDirectory.
1221
1222void TKey::ReadBuffer(char *&buffer)
1223{
1224 ReadKeyBuffer(buffer);
1225
1226 if (!gROOT->ReadingObject() && gDirectory) {
1227 if (fSeekPdir != gDirectory->GetSeekDir()) gDirectory->AppendKey(this);
1228 }
1229}
1230
1231////////////////////////////////////////////////////////////////////////////////
1232/// Decode input buffer.
1233
1234void TKey::ReadKeyBuffer(char *&buffer)
1235{
1236 frombuf(buffer, &fNbytes);
1238 frombuf(buffer,&version);
1240 frombuf(buffer, &fObjlen);
1241 fDatime.ReadBuffer(buffer);
1242 frombuf(buffer, &fKeylen);
1243 frombuf(buffer, &fCycle);
1244 if (fVersion > 1000) {
1245 frombuf(buffer, &fSeekKey);
1246
1247 // We currently store in the 16 highest bit of fSeekPdir the value of
1248 // fPidOffset. This offset is used when a key (or basket) is transfered from one
1249 // file to the other. In this case the TRef and TObject might have stored a
1250 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1251 // file, the fPidOffset is to be added to those values to correctly find the
1252 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1253 // and need to be zero for new key/basket.
1254 Long64_t pdir;
1255 frombuf(buffer, &pdir);
1258 } else {
1260 frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey;
1262 }
1263 fClassName.ReadBuffer(buffer);
1264 //the following test required for forward and backward compatibility
1265 if (fClassName == "TDirectory") {
1266 fClassName = "TDirectoryFile";
1268 }
1269
1270 fName.ReadBuffer(buffer);
1271 fTitle.ReadBuffer(buffer);
1272}
1273
1274////////////////////////////////////////////////////////////////////////////////
1275/// Read the key structure from the file
1276
1278{
1279 TFile* f = GetFile();
1280 if (f==0) return kFALSE;
1281
1283 f->Seek(fSeekKey);
1284 if( f->ReadBuffer(fBuffer,nsize) )
1285 {
1286 Error("ReadFile", "Failed to read data.");
1287 return kFALSE;
1288 }
1289 if (gDebug) {
1290 std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
1291 }
1292 return kTRUE;
1293}
1294
1295////////////////////////////////////////////////////////////////////////////////
1296/// Set parent in key buffer.
1297
1298void TKey::SetParent(const TObject *parent)
1299{
1300 if (fBufferRef) fBufferRef->SetParent((TObject*)parent);
1301}
1302
1303////////////////////////////////////////////////////////////////////////////////
1304/// Reset the key as it had not been 'filled' yet.
1305
1307{
1308 fPidOffset = 0;
1309 fNbytes = 0;
1310 fBuffer = 0;
1311 fObjlen = 0;
1312 fCycle = 0;
1313 fSeekPdir = 0;
1314 fSeekKey = 0;
1315 fLeft = 0;
1316 fDatime = (UInt_t)0;
1317
1318 // fBufferRef and fKeylen intentionally not reset/changed
1319
1321}
1322
1323////////////////////////////////////////////////////////////////////////////////
1324/// Return the size in bytes of the key header structure.
1325///
1326/// An explanation about the nbytes (Int_t nbytes) variable used in the
1327/// function. The size of fSeekKey and fSeekPdir is 8 instead of 4 if version is
1328/// greater than 1000.
1329/// | Component | Sizeof |
1330/// |-------------------|------------|
1331/// | fNbytes | 4 |
1332/// | sizeof(Version_t) | 2 |
1333/// | fObjlen | 4 |
1334/// | fDatime | 4 |
1335/// | fKeylen | 2 |
1336/// | fCycle | 2 |
1337/// | fSeekKey | 4 or 8 |
1338/// | fSeekPdir | 4 or 8 |
1339/// | **FIXED TOTAL** | 26 or 34 |
1340/// | fClassName | 1+ bytes |
1341/// | fName | 1+ bytes |
1342/// | fTitle | 1+ bytes |
1343/// | **TOTAL** | 29+ or 37+ |
1344
1346{
1347 Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8;
1348 nbytes += fDatime.Sizeof();
1350 nbytes += 11; // strlen("TDirectory")+1
1351 } else {
1353 }
1354 nbytes += fName.Sizeof();
1355 nbytes += fTitle.Sizeof();
1356 return nbytes;
1357}
1358
1359////////////////////////////////////////////////////////////////////////////////
1360/// Stream a class object.
1361
1363{
1365 if (b.IsReading()) {
1366 b >> fNbytes;
1368 b >> fObjlen;
1370 b >> fKeylen;
1371 b >> fCycle;
1372 if (fVersion > 1000) {
1373 b >> fSeekKey;
1374
1375 // We currently store in the 16 highest bit of fSeekPdir the value of
1376 // fPidOffset. This offset is used when a key (or basket) is transfered from one
1377 // file to the other. In this case the TRef and TObject might have stored a
1378 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1379 // file, the fPidOffset is to be added to those values to correctly find the
1380 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1381 // and need to be zero for new key/basket.
1382 Long64_t pdir;
1383 b >> pdir;
1386 } else {
1390 }
1392 //the following test required for forward and backward compatibility
1393 if (fClassName == "TDirectory") {
1394 fClassName = "TDirectoryFile";
1396 }
1397 fName.Streamer(b);
1398 fTitle.Streamer(b);
1399 if (fKeylen < 0) {
1400 Error("Streamer","The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero",fKeylen);
1401 MakeZombie();
1402 fKeylen = 0;
1403 }
1404 if (fObjlen < 0) {
1405 Error("Streamer","The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero",fObjlen);
1406 MakeZombie();
1407 fObjlen = 0;
1408 }
1409 if (fNbytes < 0) {
1410 Error("Streamer","The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero",fNbytes);
1411 MakeZombie();
1412 fNbytes = 0;
1413 }
1414
1415 } else {
1416 b << fNbytes;
1418 b << version;
1419 b << fObjlen;
1420 if (fDatime.Get() == 0) fDatime.Set();
1422 TDatime((UInt_t) 1).Streamer(b);
1423 else
1425 b << fKeylen;
1426 b << fCycle;
1427 if (fVersion > 1000) {
1428 b << fSeekKey;
1429
1430 // We currently store in the 16 highest bit of fSeekPdir the value of
1431 // fPidOffset. This offset is used when a key (or basket) is transfered from one
1432 // file to the other. In this case the TRef and TObject might have stored a
1433 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1434 // file, the fPidOffset is to be added to those values to correctly find the
1435 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1436 // and need to be zero for new key/basket.
1438 b << pdir;
1439 } else {
1440 b << (Int_t)fSeekKey;
1441 b << (Int_t)fSeekPdir;
1442 }
1444 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
1445 b.WriteTString(gTDirectoryString);
1446 } else {
1448 }
1449 fName.Streamer(b);
1450 fTitle.Streamer(b);
1451 }
1452}
1453
1454////////////////////////////////////////////////////////////////////////////////
1455/// Write the encoded object supported by this key.
1456/// The function returns the number of bytes committed to the file.
1457/// If a write error occurs, the number of bytes returned is -1.
1458
1460{
1461 if (!f) f = GetFile();
1462 if (!f) return -1;
1463
1465 char *buffer = fBuffer;
1466 if (cycle) {
1467 fCycle = cycle;
1468 FillBuffer(buffer);
1469 buffer = fBuffer;
1470 }
1471
1472 if (fLeft > 0) nsize += sizeof(Int_t);
1473 f->Seek(fSeekKey);
1474 Bool_t result = f->WriteBuffer(buffer,nsize);
1475 //f->Flush(); Flushing takes too much time.
1476 // Let user flush the file when they want.
1477 if (gDebug) {
1478 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1479 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1480 }
1481
1482 DeleteBuffer();
1483 return result==kTRUE ? -1 : nsize;
1484}
1485
1486////////////////////////////////////////////////////////////////////////////////
1487/// Write the encoded object supported by this key.
1488/// The function returns the number of bytes committed to the file.
1489/// If a write error occurs, the number of bytes returned is -1.
1490
1492{
1493 if (!f) f = GetFile();
1494 if (!f) return -1;
1495
1497 char *buffer = fBuffer;
1498
1499 if (fLeft > 0) nsize += sizeof(Int_t);
1500 f->Seek(fSeekKey);
1501 Bool_t result = f->WriteBuffer(buffer,nsize);
1502 //f->Flush(); Flushing takes too much time.
1503 // Let user flush the file when they want.
1504 if (gDebug) {
1505 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1506 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1507 }
1508
1509 return result==kTRUE ? -1 : nsize;
1510}
1511
1512////////////////////////////////////////////////////////////////////////////////
1513/// Title can keep 32x32 xpm thumbnail/icon of the parent object.
1514
1515const char *TKey::GetIconName() const
1516{
1517 return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0);
1518}
1519
1520////////////////////////////////////////////////////////////////////////////////
1521/// Returns title (title can contain 32x32 xpm thumbnail/icon).
1522
1523const char *TKey::GetTitle() const
1524{
1525 if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) { // title contains xpm thumbnail
1526 static TString ret;
1527 int start = fTitle.Index("/*") + 3;
1528 int stop = fTitle.Index("*/") - 1;
1529 ret = fTitle(start, stop - start);
1530 return ret.Data();
1531 }
1532 return fTitle.Data();
1533}
void frombuf(char *&buf, Bool_t *x)
Definition Bytes.h:278
void tobuf(char *&buf, Bool_t x)
Definition Bytes.h:55
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
unsigned short UShort_t
Unsigned Short integer 2 bytes (unsigned short)
Definition RtypesCore.h:54
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char)
Definition RtypesCore.h:52
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
unsigned long long ULong64_t
Portable unsigned long integer 8 bytes.
Definition RtypesCore.h:84
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
#define gFile
Definition TFile.h:430
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 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
char name[80]
Definition TGX11.cxx:110
const ULong64_t kPidOffsetMask
Definition TKey.cxx:73
static const TString gTDirectoryString("TDirectory")
const Int_t kTitleMax
Definition TKey.cxx:70
std::atomic< UInt_t > keyAbsNumber
Definition TKey.cxx:80
const UChar_t kPidOffsetShift
Definition TKey.cxx:77
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
#define gROOT
Definition TROOT.h:411
void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout)
int R__unzip_header(Int_t *nin, UChar_t *bufin, Int_t *lout)
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
Buffer base class used for serializing objects.
Definition TBuffer.h:43
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition TBuffer.cxx:269
@ kWrite
Definition TBuffer.h:73
@ kRead
Definition TBuffer.h:73
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
Int_t Length() const
Definition TBuffer.h:100
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
char * Buffer() const
Definition TBuffer.h:96
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:623
EState GetState() const
Definition TClass.h:501
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5017
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5439
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7592
@ kDummyNew
Definition TClass.h:110
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:5980
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4901
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2796
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition TClass.cxx:7490
@ kEmulated
Definition TClass.h:128
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2612
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:2973
static TClass * Class()
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
UInt_t Get() const
Return raw date/time as encoded by TDatime.
Definition TDatime.cxx:239
void FillBuffer(char *&buffer)
Encode Date/Time into buffer, used by I/O system.
Definition TDatime.cxx:228
Int_t Sizeof() const
Definition TDatime.h:81
virtual void Streamer(TBuffer &)
Stream a object of type TDatime.
Definition TDatime.cxx:415
void Set()
Set Date/Time to current time as reported by the system.
Definition TDatime.cxx:288
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition TDatime.cxx:277
A ROOT file is structured in Directories (like a file system).
static TClass * Class()
Describe directory structure in memory.
Definition TDirectory.h:45
virtual Long64_t GetSeekDir() const
Definition TDirectory.h:229
virtual TList * GetList() const
Definition TDirectory.h:223
virtual Int_t AppendKey(TKey *)
Definition TDirectory.h:185
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
virtual TFile * GetFile() const
Definition TDirectory.h:221
void SetName(const char *newname) override
Set the name for directory If the directory name is changed after the directory was written once,...
virtual void SetMother(TObject *mother)
Definition TDirectory.h:259
virtual TList * GetListOfKeys() const
Definition TDirectory.h:224
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
Int_t GetCompressionLevel() const
Definition TFile.h:474
virtual Long64_t GetEND() const
Definition TFile.h:310
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition TFile.cxx:1473
Int_t GetCompressionAlgorithm() const
Definition TFile.h:468
@ kReproducible
Definition TFile.h:272
@ kStartBigFile
Definition TFile.h:279
Service class for TFile.
Definition TFree.h:27
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
const char * GetTitle() const override
Returns title (title can contain 32x32 xpm thumbnail/icon).
Definition TKey.cxx:1523
static constexpr Version_t Class_Version()
Definition TKey.h:116
void Delete(Option_t *option="") override
Delete an object from the file.
Definition TKey.cxx:540
@ kReproducible
Definition TKey.h:33
@ kIsDirectoryFile
Definition TKey.h:32
Int_t Sizeof() const override
Return the size in bytes of the key header structure.
Definition TKey.cxx:1345
TKey()
TKey default constructor.
Definition TKey.cxx:86
~TKey() override
TKey default destructor.
Definition TKey.cxx:527
TFile * GetFile() const
Returns file to which key belong.
Definition TKey.cxx:587
virtual void Keep()
Set the "KEEP" status.
Definition TKey.cxx:687
const char * GetIconName() const override
Title can keep 32x32 xpm thumbnail/icon of the parent object.
Definition TKey.cxx:1515
Int_t Read(const char *name) override
Read contents of object with specified name from the current directory.
Definition TKey.h:54
TDatime fDatime
Date/Time of insertion in file.
Definition TKey.h:42
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition TKey.h:50
UShort_t fPidOffset
!Offset to be added to the pid index in this key/buffer. This is actually saved in the high bits of f...
Definition TKey.h:51
virtual void IncrementPidOffset(UShort_t offset)
Increment fPidOffset by 'offset'.
Definition TKey.cxx:652
Short_t GetKeep() const
Returns the "KEEP" status.
Definition TKey.cxx:595
Int_t fVersion
Key version identifier.
Definition TKey.h:39
Bool_t IsFolder() const override
Check if object referenced by the key is a folder.
Definition TKey.cxx:666
Int_t fLeft
Number of bytes left in current segment.
Definition TKey.h:48
virtual const char * GetClassName() const
Definition TKey.h:75
Short_t fKeylen
Number of bytes for the key itself.
Definition TKey.h:43
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition TKey.cxx:1277
void Browse(TBrowser *b) override
Read object from disk and call its Browse() method.
Definition TKey.cxx:429
virtual Int_t WriteFileKeepBuffer(TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1491
Long64_t fSeekKey
Location of object on file.
Definition TKey.h:45
void Build(TDirectory *motherDir, const char *classname, Long64_t filepos)
Method used in all TKey constructor to initialize basic data fields.
Definition TKey.cxx:391
char * fBuffer
Object buffer.
Definition TKey.h:49
Long64_t fSeekPdir
Location of parent directory on file.
Definition TKey.h:46
virtual void SetParent(const TObject *parent)
Set parent in key buffer.
Definition TKey.cxx:1298
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition TKey.cxx:1025
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1234
Int_t fNbytes
Number of bytes for the object on file.
Definition TKey.h:40
Int_t fObjlen
Length of uncompressed object in bytes.
Definition TKey.h:41
void Reset()
Reset the key as it had not been 'filled' yet.
Definition TKey.cxx:1306
Short_t fCycle
Cycle number.
Definition TKey.h:44
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition TKey.cxx:894
virtual void ls(Bool_t current) const
List Key contents.
Definition TKey.cxx:696
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:579
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:760
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
Definition TKey.cxx:461
virtual void DeleteBuffer()
Delete key buffer(s).
Definition TKey.cxx:561
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1459
virtual void ReadBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1222
TDirectory * fMotherDir
!pointer to mother directory
Definition TKey.h:52
TString fClassName
Object Class name.
Definition TKey.h:47
void Print(Option_t *option="") const override
Print key contents.
Definition TKey.cxx:716
void FillBuffer(char *&buffer) override
Encode key header into output buffer.
Definition TKey.cxx:603
void Streamer(TBuffer &) override
Stream a class object.
Definition TKey.cxx:1362
A doubly linked list.
Definition TList.h:38
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
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:573
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:972
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
static TClass * Class()
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1099
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:875
virtual TClass * IsA() const
Definition TObject.h:246
void MakeZombie()
Definition TObject.h:53
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2898
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
const char * Data() const
Definition TString.h:384
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition TString.cxx:1159
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:631
Bool_t IsNull() const
Definition TString.h:422
virtual void FillBuffer(char *&buffer) const
Copy string into I/O buffer.
Definition TString.cxx:1316
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1418
virtual Int_t Sizeof() const
Returns size string will occupy on I/O buffer.
Definition TString.cxx:1407
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition TString.cxx:1337
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:659
TF1 * f1
Definition legend1.C:11
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition Rtypes.h:120
EValues
Note: this is only temporarily a struct and will become a enum class hence the name convention used.
Definition Compression.h:88