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
83
84////////////////////////////////////////////////////////////////////////////////
85/// TKey default constructor.
86
87TKey::TKey() : TNamed(), fDatime((UInt_t)0)
88{
89 Build(0, "", 0);
90
91 fKeylen = Sizeof();
92
94}
95
96////////////////////////////////////////////////////////////////////////////////
97/// TKey default constructor.
98
100{
101 Build(motherDir, "", 0);
102
103 fKeylen = Sizeof();
104
106}
107
108////////////////////////////////////////////////////////////////////////////////
109/// Copy a TKey from its original directory to the new 'motherDir'
110
112{
114
115 fPidOffset = orig.fPidOffset + pidOffset;
116 fNbytes = orig.fNbytes;
117 fObjlen = orig.fObjlen;
118 fClassName = orig.fClassName;
119 fName = orig.fName;
120 fTitle = orig.fTitle;
121
122 fCycle = fMotherDir->AppendKey(this);
123 fSeekPdir = 0;
124 fSeekKey = 0;
125 fLeft = 0;
126
130
131 fKeylen = Sizeof(); // fVersion must be set.
132
135 UInt_t alloc = fNbytes + sizeof(Int_t); // The extra Int_t is for any free space information.
136 if (fKeylen < orig.fKeylen) {
137 bufferDecOffset = orig.fKeylen - fKeylen;
139 } else if (fKeylen > orig.fKeylen) {
140 bufferIncOffset = fKeylen - orig.fKeylen;
143 }
144
147
148 // Steal the data from the old key.
149
150 TFile* f = orig.GetFile();
151 if (f) {
152 Int_t nsize = orig.fNbytes;
153 f->Seek(orig.fSeekKey);
154 if( f->ReadBuffer(fBuffer+bufferIncOffset,nsize) )
155 {
156 Error("ReadFile", "Failed to read data.");
157 return;
158 }
159 if (gDebug) {
160 std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
161 }
162 }
163 fBuffer += bufferDecOffset; // Reset the buffer to be appropriate for this key.
165 Create(nout);
167 Streamer(*fBufferRef); //write key itself again
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// Create a TKey object to read keys.
172/// Constructor called by TDirectoryFile::ReadKeys and by TFile::TFile.
173/// A TKey object is created to read the keys structure itself.
174
176{
177 Build(motherDir, "", pointer);
178
179 fSeekKey = pointer;
180 fNbytes = nbytes;
181 fBuffer = new char[nbytes];
183}
184
185////////////////////////////////////////////////////////////////////////////////
186/// Create a TKey object with the specified name, title for the given class.
187///
188/// WARNING: in name avoid special characters like '^','$','.' that are used
189/// by the regular expression parser (see TRegexp).
190
191TKey::TKey(const char *name, const char *title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
192 : TNamed(name,title)
193{
194 Build(motherDir, cl->GetName(), -1);
195
196 fKeylen = Sizeof();
197 fObjlen = nbytes;
198 Create(nbytes);
199}
200
201////////////////////////////////////////////////////////////////////////////////
202/// Create a TKey object with the specified name, title for the given class.
203///
204/// WARNING: in name avoid special characters like '^','$','.' that are used
205/// by the regular expression parser (see TRegexp).
206
208 : TNamed(name,title)
209{
210 Build(motherDir, cl->GetName(), -1);
211
212 fKeylen = Sizeof();
213 fObjlen = nbytes;
214 Create(nbytes);
215}
216
217////////////////////////////////////////////////////////////////////////////////
218/// Create a TKey object for a TObject* and fill output buffer
219///
220/// WARNING: in name avoid special characters like '^','$','.' that are used
221/// by the regular expression parser (see TRegexp).
222
224 : TNamed(name, obj->GetTitle())
225{
226 R__ASSERT(obj);
227
228 if (!obj->IsA()->HasDefaultConstructor()) {
229 Warning("TKey", "since %s has no public constructor\n"
230 "\twhich can be called without argument, objects of this class\n"
231 "\tcan not be read with the current library. You will need to\n"
232 "\tadd a default constructor before attempting to read it.",
233 obj->ClassName());
234 }
235
236 Build(motherDir, obj->ClassName(), -1);
237
238 Int_t lbuf, nout, noutot, bufmax, nzip;
241 fCycle = fMotherDir->AppendKey(this);
242
243 Streamer(*fBufferRef); //write key itself
245 fBufferRef->MapObject(obj); //register obj in map in case of self reference
246 ((TObject*)obj)->Streamer(*fBufferRef); //write object
248 fObjlen = lbuf - fKeylen;
249
252 if (cxlevel > 0 && fObjlen > 256) {
253 Int_t nbuffers = 1 + (fObjlen - 1)/kMAXZIPBUF;
254 Int_t buflen = std::max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
255 fBuffer = new char[buflen];
256 char *objbuf = fBufferRef->Buffer() + fKeylen;
257 char *bufcur = &fBuffer[fKeylen];
258 noutot = 0;
259 nzip = 0;
260 for (Int_t i = 0; i < nbuffers; ++i) {
261 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
262 else bufmax = kMAXZIPBUF;
264 if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
265 delete[] fBuffer;
266 bufcur = nullptr;
270 Streamer(*fBufferRef); //write key itself again
271 return;
272 }
273 bufcur += nout;
274 noutot += nout;
276 nzip += kMAXZIPBUF;
277 }
278 Create(noutot);
280 Streamer(*fBufferRef); //write key itself again
282 delete fBufferRef; fBufferRef = 0;
283 } else {
287 Streamer(*fBufferRef); //write key itself again
288 }
289}
290
291////////////////////////////////////////////////////////////////////////////////
292/// Create a TKey object for any object obj of class cl d and fill
293/// output buffer.
294///
295/// WARNING: in name avoid special characters like '^','$','.' that are used
296/// by the regular expression parser (see TRegexp).
297
298TKey::TKey(const void *obj, const TClass *cl, const char *name, Int_t bufsize, TDirectory *motherDir) : TNamed(name, "")
299{
300 R__ASSERT(obj && cl);
301
302 if (!cl->HasDefaultConstructor()) {
303 Warning("TKey", "since %s has no public constructor\n"
304 "\twhich can be called without argument, objects of this class\n"
305 "\tcan not be read with the current library. You will need to\n"
306 "\tadd a default constructor before attempting to read it.",
307 cl->GetName());
308 }
309
310 TClass *clActual = cl->GetActualClass(obj);
311 const void* actualStart;
312 if (clActual) {
313 const char *temp = (const char*) obj;
314 // clActual->GetStreamerInfo();
315 Int_t offset = (cl != clActual) ?
316 clActual->GetBaseClassOffset(cl) : 0;
317 temp -= offset;
318 actualStart = temp;
319 } else {
320 // We could not determine the real type of this object,
321 // let's assume it is the one given by the caller.
322 clActual = const_cast<TClass*>(cl);
323 actualStart = obj;
324 }
325
326 Build(motherDir, clActual->GetName(), -1);
327
330
331 Streamer(*fBufferRef); //write key itself
333
334 Int_t lbuf, nout, noutot, bufmax, nzip;
335
336 fBufferRef->MapObject(actualStart,clActual); //register obj in map in case of self reference
337 clActual->Streamer((void*)actualStart, *fBufferRef); //write object
339 fObjlen = lbuf - fKeylen;
340
341 // Append to mother directory only after the call to Streamer() was
342 // successful (and didn't throw).
343 fCycle = fMotherDir->AppendKey(this);
344
347 if (cxlevel > 0 && fObjlen > 256) {
348 Int_t nbuffers = 1 + (fObjlen - 1)/kMAXZIPBUF;
349 Int_t buflen = std::max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
350 fBuffer = new char[buflen];
351 char *objbuf = fBufferRef->Buffer() + fKeylen;
352 char *bufcur = &fBuffer[fKeylen];
353 noutot = 0;
354 nzip = 0;
355 for (Int_t i = 0; i < nbuffers; ++i) {
356 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
357 else bufmax = kMAXZIPBUF;
359 if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
360 delete[] fBuffer;
361 bufcur = nullptr;
365 Streamer(*fBufferRef); //write key itself again
366 return;
367 }
368 bufcur += nout;
369 noutot += nout;
371 nzip += kMAXZIPBUF;
372 }
373 Create(noutot);
375 Streamer(*fBufferRef); //write key itself again
377 delete fBufferRef; fBufferRef = 0;
378 } else {
382 Streamer(*fBufferRef); //write key itself again
383 }
384}
385
386////////////////////////////////////////////////////////////////////////////////
387/// Method used in all TKey constructor to initialize basic data fields.
388///
389/// The member filepos is used to calculate correct version number of key
390/// if filepos==-1, end of file position is used.
391
392void TKey::Build(TDirectory* motherDir, const char* classname, Long64_t filepos)
393{
395
396 fPidOffset = 0;
397 fNbytes = 0;
398 fBuffer = 0;
399 fKeylen = 0;
400 fObjlen = 0;
401 fBufferRef = 0;
402 fCycle = 0;
403 fSeekPdir = 0;
404 fSeekKey = 0;
405 fLeft = 0;
406
407 fClassName = classname;
408 //the following test required for forward and backward compatibility
409 if (fClassName == "TDirectoryFile") SetBit(kIsDirectoryFile);
410
412
413 if ((filepos==-1) && GetFile()) filepos = GetFile()->GetEND();
415
417
420}
421
422////////////////////////////////////////////////////////////////////////////////
423/// Read object from disk and call its Browse() method.
424///
425/// If object with same name already exist in memory delete it (like
426/// TDirectoryFile::Get() is doing), except when the key references a
427/// folder in which case we don't want to re-read the folder object
428/// since it might contain new objects not yet saved.
429
431{
432 if (fMotherDir==0) return;
433
435
436 void* obj = fMotherDir->GetList()->FindObject(GetName());
437 if (obj && objcl->IsTObject()) {
438 TObject *tobj = (TObject*) objcl->DynamicCast(TObject::Class(), obj);
439 if (!tobj->IsFolder()) {
440 if (tobj->InheritsFrom(TCollection::Class()))
441 tobj->Delete(); // delete also collection elements
442 delete tobj;
443 obj = 0;
444 }
445 }
446
447 if (!obj)
448 obj = ReadObj();
449
450 if (b && obj) {
451 objcl->Browse(obj,b);
452 b->SetRefreshFlag(kTRUE);
453 }
454}
455
456////////////////////////////////////////////////////////////////////////////////
457/// Create a TKey object of specified size.
458///
459/// If externFile!=0, key will be allocated in specified file, otherwise file
460/// of mother directory will be used.
461
463{
465
466 TFile *f = externFile;
467 if (!f) f = GetFile();
468 if (!f) {
469 Error("Create","Cannot create key without file");
470 return;
471 }
472
474 TList *lfree = f->GetListOfFree();
475 TFree *f1 = (TFree*)lfree->First();
476//*-*-------------------find free segment
477//*-* =================
478 TFree *bestfree = f1->GetBestFree(lfree,nsize);
479 if (bestfree == 0) {
480 Error("Create","Cannot allocate %d bytes for ID = %s Title = %s",
482 return;
483 }
484
485 if (f->TestBit(TFile::kReproducible))
487
488 fDatime.Set();
489 fSeekKey = bestfree->GetFirst();
490//*-*----------------- Case Add at the end of the file
491 if (fSeekKey >= f->GetEND()) {
492 f->SetEND(fSeekKey+nsize);
493 bestfree->SetFirst(fSeekKey+nsize);
494 if (f->GetEND() > bestfree->GetLast()) {
495 bestfree->SetLast(bestfree->GetLast() + 1000000000);
496 }
497 fLeft = -1;
498 if (!fBuffer) fBuffer = new char[nsize];
499 } else {
500 fLeft = Int_t(bestfree->GetLast() - fSeekKey - nsize + 1);
501 }
502//*-*----------------- Case where new object fills exactly a deleted gap
503 fNbytes = nsize;
504 if (fLeft == 0) {
505 if (!fBuffer) {
506 fBuffer = new char[nsize];
507 }
508 lfree->Remove(bestfree);
509 delete bestfree;
510 }
511//*-*----------------- Case where new object is placed in a deleted gap larger than itself
512 if (fLeft > 0) { // found a bigger segment
513 if (!fBuffer) {
514 fBuffer = new char[nsize+sizeof(Int_t)];
515 }
516 char *buffer = fBuffer+nsize;
517 Int_t nbytesleft = -fLeft; // set header of remaining record
518 tobuf(buffer, nbytesleft);
519 bestfree->SetFirst(fSeekKey+nsize);
520 }
521
522 fSeekPdir = externFile ? externFile->GetSeekDir() : fMotherDir->GetSeekDir();
523}
524
525////////////////////////////////////////////////////////////////////////////////
526/// TKey default destructor.
527
529{
531 fMotherDir->GetListOfKeys()->Remove(this);
533}
534
535////////////////////////////////////////////////////////////////////////////////
536/// Delete an object from the file.
537///
538/// Note: the key is not deleted. You still have to call "delete key".
539/// This is different from the behaviour of TObject::Delete()!
540
542{
544 // TDirectoryFile assumes that its location on file never change (for example updates are partial)
545 // and never checks if the space might have been released and thus over-write any data that might
546 // have been written there.
547 if (option && option[0] == 'v')
548 printf("Rejected attempt to delete TDirectoryFile key: %s at address %lld, nbytes = %d\n",
550 return;
551 }
552 if (option && option[0] == 'v') printf("Deleting key: %s at address %lld, nbytes = %d\n",GetName(),fSeekKey,fNbytes);
553 Long64_t first = fSeekKey;
554 Long64_t last = fSeekKey + fNbytes -1;
555 if (GetFile()) GetFile()->MakeFree(first, last); // release space used by this key
556 fMotherDir->GetListOfKeys()->Remove(this);
557}
558
559////////////////////////////////////////////////////////////////////////////////
560/// Delete key buffer(s).
561
563{
564 if (fBufferRef) {
565 delete fBufferRef;
566 fBufferRef = 0;
567 } else {
568 // We only need to delete fBuffer if fBufferRef is zero because
569 // if fBufferRef exists, we delegate ownership of fBuffer to fBufferRef.
570 if (fBuffer) {
571 delete [] fBuffer;
572 }
573 }
574 fBuffer = 0;
575}
576
577////////////////////////////////////////////////////////////////////////////////
578/// Return cycle number associated to this key.
579
581{
582 return ((fCycle >0) ? fCycle : -fCycle);
583}
584
585////////////////////////////////////////////////////////////////////////////////
586/// Returns file to which key belong.
587
589{
590 return fMotherDir!=0 ? fMotherDir->GetFile() : gFile;
591}
592
593////////////////////////////////////////////////////////////////////////////////
594/// Returns the "KEEP" status.
595
597{
598 return ((fCycle >0) ? 0 : 1);
599}
600
601////////////////////////////////////////////////////////////////////////////////
602/// Encode key header into output buffer.
603
604void TKey::FillBuffer(char *&buffer)
605{
606 tobuf(buffer, fNbytes);
608 tobuf(buffer, version);
609
610 tobuf(buffer, fObjlen);
612 TDatime((UInt_t) 1).FillBuffer(buffer);
613 else
614 fDatime.FillBuffer(buffer);
615 tobuf(buffer, fKeylen);
616 tobuf(buffer, fCycle);
617 if (fVersion > 1000) {
618 tobuf(buffer, fSeekKey);
619
620 // We currently store in the 16 highest bit of fSeekPdir the value of
621 // fPidOffset. This offset is used when a key (or basket) is transfered from one
622 // file to the other. In this case the TRef and TObject might have stored a
623 // pid index (to retrieve TProcessIDs) which refered to their order on the original
624 // file, the fPidOffset is to be added to those values to correctly find the
625 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
626 // and need to be zero for new key/basket.
628 tobuf(buffer, pdir);
629 } else {
630 tobuf(buffer, (Int_t)fSeekKey);
631 tobuf(buffer, (Int_t)fSeekPdir);
632 }
634 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
635 gTDirectoryString.FillBuffer(buffer);
636 } else {
637 fClassName.FillBuffer(buffer);
638 }
639 fName.FillBuffer(buffer);
640 fTitle.FillBuffer(buffer);
641}
642
643////////////////////////////////////////////////////////////////////////////////
644/// Increment fPidOffset by 'offset'.
645///
646/// This offset is used when a key (or basket) is transfered from one file to
647/// the other. In this case the TRef and TObject might have stored a pid
648/// index (to retrieve TProcessIDs) which refered to their order on the
649/// original file, the fPidOffset is to be added to those values to correctly
650/// find the TProcessID. This fPidOffset needs to be increment if the
651/// key/basket is copied and need to be zero for new key/basket.
652
654{
656 if (fPidOffset) {
657 // We currently store fPidOffset in the 16 highest bit of fSeekPdir, which
658 // need to be store as a 64 bit integer. So we require this key to be
659 // a 'large file' key.
660 if (fVersion<1000) fVersion += 1000;
661 }
662}
663
664////////////////////////////////////////////////////////////////////////////////
665/// Check if object referenced by the key is a folder.
666
668{
669 Bool_t ret = kFALSE;
670
671 TClass *classPtr = TClass::GetClass((const char *) fClassName);
672 if (classPtr && classPtr->GetState() > TClass::kEmulated && classPtr->IsTObject()) {
673 TObject *obj = (TObject *) classPtr->DynamicCast(TObject::Class(), classPtr->New(TClass::kDummyNew));
674 if (obj) {
675 ret = obj->IsFolder();
676 delete obj;
677 }
678 }
679
680 return ret;
681}
682
683////////////////////////////////////////////////////////////////////////////////
684/// Set the "KEEP" status.
685///
686/// When the KEEP flag is set to 1 the object cannot be purged.
687
689{
690 if (fCycle >0) fCycle = -fCycle;
691}
692
693////////////////////////////////////////////////////////////////////////////////
694/// List Key contents.
695/// Add indicator of whether it is the current item or a backup copy.
696
697void TKey::ls(Bool_t current) const
698{
700 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle();
701 std::cout << (current ? " [current cycle]" : " [backup cycle]");
702 std::cout <<std::endl;
703}
704
705////////////////////////////////////////////////////////////////////////////////
706/// List Key contents.
707
708void TKey::ls(Option_t *) const
709{
711 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<std::endl;
712}
713
714////////////////////////////////////////////////////////////////////////////////
715/// Print key contents.
716
718{
719 printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle());
720}
721
722////////////////////////////////////////////////////////////////////////////////
723/// To read a TObject* from the file.
724///
725/// The object associated to this key is read from the file into memory
726/// Once the key structure is read (via Streamer) the class identifier
727/// of the object is known.
728/// Using the class identifier we find the TClass object for this class.
729/// A TClass object contains a full description (i.e. dictionary) of the
730/// associated class. In particular the TClass object can create a new
731/// object of the class type it describes. This new object now calls its
732/// Streamer function to rebuilt itself.
733///
734/// Use TKey::ReadObjectAny to read any object non-derived from TObject
735///
736/// ### Note
737/// A C style cast can only be used in the case where the final class
738/// of this object derives from TObject as a first inheritance, otherwise
739/// one must use a dynamic_cast.
740///
741/// #### Example1: simplified case
742/// ~~~{.cpp}
743/// class MyClass : public TObject, public AnotherClass
744/// ~~~
745/// then on return, one get away with using:
746/// ~~~{.cpp}
747/// MyClass *obj = (MyClass*)key->ReadObj();
748/// ~~~
749///
750/// #### Example2: Usual case (recommended unless performance is critical)
751/// ~~~{.cpp}
752/// MyClass *obj = dynamic_cast<MyClass*>(key->ReadObj());
753/// ~~~
754/// which support also the more complex inheritance like:
755/// ~~~{.cpp}
756/// class MyClass : public AnotherClass, public TObject
757/// ~~~
758///
759/// Of course, `dynamic_cast<>` can also be used in the example 1.
760
762{
764 if (!cl) {
765 Error("ReadObj", "Unknown class %s", fClassName.Data());
766 return 0;
767 }
768 if (!cl->IsTObject()) {
769 // in principle user should call TKey::ReadObjectAny!
770 return (TObject*)ReadObjectAny(0);
771 }
772
774 if (!bufferRef.Buffer()) {
775 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
776 return 0;
777 }
778 if (GetFile()==0) return 0;
779 bufferRef.SetParent(GetFile());
780 bufferRef.SetPidOffset(fPidOffset);
781
782 std::unique_ptr<char []> compressedBuffer;
783 auto storeBuffer = fBuffer;
784 if (fObjlen > fNbytes-fKeylen) {
785 compressedBuffer.reset(new char[fNbytes]);
787 if( !ReadFile() ) //Read object structure from file
788 {
789 fBuffer = 0;
790 return 0;
791 }
793 } else {
794 fBuffer = bufferRef.Buffer();
795 if( !ReadFile() ) { //Read object structure from file
796
797 fBuffer = 0;
798 return 0;
799 }
800 }
802
803 // get version of key
804 bufferRef.SetBufferOffset(sizeof(fNbytes));
805 Version_t kvers = bufferRef.ReadVersion();
806
807 bufferRef.SetBufferOffset(fKeylen);
808 TObject *tobj = 0;
809 // Create an instance of this class
810
811 char *pobj = (char*)cl->New();
812 if (!pobj) {
813 Error("ReadObj", "Cannot create new object of class %s", fClassName.Data());
814 return 0;
815 }
817 if (baseOffset==-1) {
818 // cl does not inherit from TObject.
819 // Since this is not possible yet, the only reason we could reach this code
820 // is because something is screw up in the ROOT code.
821 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
822 fClassName.Data());
823 }
825 if (kvers > 1)
826 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
827
828 if (fObjlen > fNbytes-fKeylen) {
829 char *objbuf = bufferRef.Buffer() + fKeylen;
831 Int_t nin, nout = 0, nbuf;
832 Int_t noutot = 0;
833 while (1) {
835 if (hc!=0) break;
836 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
837 if (!nout) break;
838 noutot += nout;
839 if (noutot >= fObjlen) break;
840 bufcur += nin;
841 objbuf += nout;
842 }
843 compressedBuffer.reset(nullptr);
844 if (nout) {
845 tobj->Streamer(bufferRef); //does not work with example 2 above
846 } else {
847 // Even-though we have a TObject, if the class is emulated the virtual
848 // table may not be 'right', so let's go via the TClass.
849 cl->Destructor(pobj);
850 return nullptr;
851 }
852 } else {
853 tobj->Streamer(bufferRef);
854 }
855
856 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
857
859 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
860 dir->SetName(GetName());
861 dir->SetTitle(GetTitle());
862 dir->SetMother(fMotherDir);
863 fMotherDir->Append(dir);
864 }
865
866 // Append the object to the directory if requested:
867 {
869 if (addfunc) {
870 addfunc(pobj, fMotherDir);
871 }
872 }
873
874 return tobj;
875}
876
877////////////////////////////////////////////////////////////////////////////////
878/// To read a TObject* from bufferRead.
879///
880/// This function is identical to TKey::ReadObj, but it reads directly from
881/// bufferRead instead of reading from a file.
882/// The object associated to this key is read from the buffer into memory
883/// Using the class identifier we find the TClass object for this class.
884/// A TClass object contains a full description (i.e. dictionary) of the
885/// associated class. In particular the TClass object can create a new
886/// object of the class type it describes. This new object now calls its
887/// Streamer function to rebuilt itself.
888///
889/// ### Note
890/// This function is called only internally by ROOT classes.
891/// Although being public it is not supposed to be used outside ROOT.
892/// If used, you must make sure that the bufferRead is large enough to
893/// accomodate the object being read.
894
896{
897
899 if (!cl) {
900 Error("ReadObjWithBuffer", "Unknown class %s", fClassName.Data());
901 return 0;
902 }
903 if (!cl->IsTObject()) {
904 // in principle user should call TKey::ReadObjectAny!
905 return (TObject*)ReadObjectAny(0);
906 }
907
909 if (!bufferRef.Buffer()) {
910 Error("ReadObjWithBuffer", "Cannot allocate buffer: fObjlen = %d", fObjlen);
911 return 0;
912 }
913 if (GetFile()==0) return 0;
914 bufferRef.SetParent(GetFile());
915 bufferRef.SetPidOffset(fPidOffset);
916
917 auto storeBuffer = fBuffer;
918 if (fObjlen > fNbytes-fKeylen) {
921 } else {
922 fBuffer = bufferRef.Buffer();
923 ReadFile(); //Read object structure from file
924 }
926
927 // get version of key
928 bufferRef.SetBufferOffset(sizeof(fNbytes));
929 Version_t kvers = bufferRef.ReadVersion();
930
931 bufferRef.SetBufferOffset(fKeylen);
932 TObject *tobj = 0;
933 // Create an instance of this class
934
935 char *pobj = (char*)cl->New();
936 if (!pobj) {
937 Error("ReadObjWithBuffer", "Cannot create new object of class %s", fClassName.Data());
938 return 0;
939 }
941 if (baseOffset==-1) {
942 // cl does not inherit from TObject.
943 // Since this is not possible yet, the only reason we could reach this code
944 // is because something is screw up in the ROOT code.
945 Fatal("ReadObjWithBuffer","Incorrect detection of the inheritance from TObject for class %s.\n",
946 fClassName.Data());
947 }
949
950 if (kvers > 1)
951 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
952
953 if (fObjlen > fNbytes-fKeylen) {
954 char *objbuf = bufferRef.Buffer() + fKeylen;
956 Int_t nin, nout = 0, nbuf;
957 Int_t noutot = 0;
958 while (1) {
960 if (hc!=0) break;
961 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
962 if (!nout) break;
963 noutot += nout;
964 if (noutot >= fObjlen) break;
965 bufcur += nin;
966 objbuf += nout;
967 }
968 if (nout) {
969 tobj->Streamer(bufferRef); //does not work with example 2 above
970 } else {
971 // Even-though we have a TObject, if the class is emulated the virtual
972 // table may not be 'right', so let's go via the TClass.
973 cl->Destructor(pobj);
974 return nullptr;
975 }
976 } else {
977 tobj->Streamer(bufferRef);
978 }
979
980 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
981
983 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
984 dir->SetName(GetName());
985 dir->SetTitle(GetTitle());
986 dir->SetMother(fMotherDir);
987 fMotherDir->Append(dir);
988 }
989
990 // Append the object to the directory if requested:
991 {
993 if (addfunc) {
994 addfunc(pobj, fMotherDir);
995 }
996 }
997
998 return tobj;
999}
1000
1001////////////////////////////////////////////////////////////////////////////////
1002/// To read an object (non deriving from TObject) from the file.
1003///
1004/// If expectedClass is not null, we checked that that actual class of the
1005/// object stored is suitable to be stored in a pointer pointing to an object
1006/// of class 'expectedClass'. We also adjust the value of the returned address
1007/// so that it is suitable to be cast (C-Style)
1008/// a pointer pointing to an object of class 'expectedClass'.
1009///
1010/// So for example if the class Bottom inherits from Top and the object
1011/// stored is of type Bottom you can safely do:
1012/// ~~~{.cpp}
1013/// auto TopClass = TClass::GetClass("Top");
1014/// auto ptr = (Top*) key->ReadObjectAny( TopClass );
1015/// if (ptr==0) printError("the object stored in the key is not of the expected type\n");
1016/// ~~~
1017/// The object associated to this key is read from the file into memory.
1018/// Once the key structure is read (via Streamer) the class identifier
1019/// of the object is known.
1020/// Using the class identifier we find the TClass object for this class.
1021/// A TClass object contains a full description (i.e. dictionary) of the
1022/// associated class. In particular the TClass object can create a new
1023/// object of the class type it describes. This new object now calls its
1024/// Streamer function to rebuilt itself.
1025
1027{
1029 if (!bufferRef.Buffer()) {
1030 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
1031 return 0;
1032 }
1033 if (GetFile()==0) return 0;
1034 bufferRef.SetParent(GetFile());
1035 bufferRef.SetPidOffset(fPidOffset);
1036
1037 std::unique_ptr<char []> compressedBuffer;
1038 auto storeBuffer = fBuffer;
1039 if (fObjlen > fNbytes-fKeylen) {
1040 compressedBuffer.reset(new char[fNbytes]);
1041 fBuffer = compressedBuffer.get();
1042 ReadFile(); //Read object structure from file
1043 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1044 } else {
1045 fBuffer = bufferRef.Buffer();
1046 ReadFile(); //Read object structure from file
1047 }
1049
1050 // get version of key
1051 bufferRef.SetBufferOffset(sizeof(fNbytes));
1052 Version_t kvers = bufferRef.ReadVersion();
1053
1054 bufferRef.SetBufferOffset(fKeylen);
1056 TClass *clOnfile = 0;
1057 if (!cl) {
1058 Error("ReadObjectAny", "Unknown class %s", fClassName.Data());
1059 return 0;
1060 }
1061 Int_t baseOffset = 0;
1062 if (expectedClass) {
1063 // baseOffset will be -1 if cl does not inherit from expectedClass
1065 if (baseOffset == -1) {
1066 // The 2 classes are unrelated, maybe there is a converter between the 2.
1067
1068 if (!expectedClass->GetSchemaRules() ||
1069 !expectedClass->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()))
1070 {
1071 // There is no converter
1072 return 0;
1073 }
1074 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 ....
1075 clOnfile = cl;
1076 cl = const_cast<TClass*>(expectedClass);
1077 if (gDebug > 0)
1078 Info("ReadObjectAny", "Using Converter StreamerInfo from %s to %s", clOnfile->GetName(),
1079 expectedClass->GetName());
1080 }
1081 if (cl->GetState() > TClass::kEmulated && expectedClass->GetState() <= TClass::kEmulated) {
1082 //we cannot mix a compiled class with an emulated class in the inheritance
1083 Warning("ReadObjectAny",
1084 "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
1085 cl->GetName(),expectedClass->GetName());
1086 }
1087 }
1088 // Create an instance of this class
1089
1090 void *pobj = cl->New();
1091 if (!pobj) {
1092 Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data());
1093 return 0;
1094 }
1095
1096 if (kvers > 1)
1097 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
1098
1099 if (fObjlen > fNbytes-fKeylen) {
1100 char *objbuf = bufferRef.Buffer() + fKeylen;
1102 Int_t nin, nout = 0, nbuf;
1103 Int_t noutot = 0;
1104 while (1) {
1106 if (hc!=0) break;
1107 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1108 if (!nout) break;
1109 noutot += nout;
1110 if (noutot >= fObjlen) break;
1111 bufcur += nin;
1112 objbuf += nout;
1113 }
1114 if (nout) {
1115 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1116 } else {
1117 cl->Destructor(pobj);
1118 return nullptr;
1119 }
1120 } else {
1121 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1122 }
1123
1124 if (cl->IsTObject()) {
1126 if (tobjBaseOffset == -1) {
1127 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
1128 fClassName.Data());
1129 }
1130 TObject *tobj = (TObject*)( ((char*)pobj) + tobjBaseOffset);
1131
1132 // See similar adjustments in ReadObj
1133 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
1134
1136 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1137 dir->SetName(GetName());
1138 dir->SetTitle(GetTitle());
1139 dir->SetMother(fMotherDir);
1140 fMotherDir->Append(dir);
1141 }
1142 }
1143
1144 {
1145 // Append the object to the directory if requested:
1147 if (addfunc) {
1148 addfunc(pobj, fMotherDir);
1149 }
1150 }
1151
1152 return ( ((char*)pobj) + baseOffset );
1153}
1154
1155////////////////////////////////////////////////////////////////////////////////
1156/// To read an object from the file.
1157///
1158/// The object associated to this key is read from the file into memory.
1159/// Before invoking this function, obj has been created via the
1160/// default constructor.
1161
1163{
1164 if (!obj || (GetFile()==0)) return 0;
1165
1167 bufferRef.SetParent(GetFile());
1168 bufferRef.SetPidOffset(fPidOffset);
1169
1170 if (fVersion > 1)
1171 bufferRef.MapObject(obj); //register obj in map to handle self reference
1172
1173 std::unique_ptr<char []> compressedBuffer;
1174 auto storeBuffer = fBuffer;
1175 if (fObjlen > fNbytes-fKeylen) {
1176 compressedBuffer.reset(new char[fNbytes]);
1177 fBuffer = compressedBuffer.get();
1178 ReadFile(); //Read object structure from file
1179 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1180 } else {
1181 fBuffer = bufferRef.Buffer();
1182 ReadFile(); //Read object structure from file
1183 }
1185
1186 bufferRef.SetBufferOffset(fKeylen);
1187 if (fObjlen > fNbytes-fKeylen) {
1188 char *objbuf = bufferRef.Buffer() + fKeylen;
1190 Int_t nin, nout = 0, nbuf;
1191 Int_t noutot = 0;
1192 while (1) {
1194 if (hc!=0) break;
1195 R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1196 if (!nout) break;
1197 noutot += nout;
1198 if (noutot >= fObjlen) break;
1199 bufcur += nin;
1200 objbuf += nout;
1201 }
1202 if (nout) obj->Streamer(bufferRef);
1203 } else {
1204 obj->Streamer(bufferRef);
1205 }
1206
1207 // Append the object to the directory if requested:
1208 {
1209 ROOT::DirAutoAdd_t addfunc = obj->IsA()->GetDirectoryAutoAdd();
1210 if (addfunc) {
1211 addfunc(obj, fMotherDir);
1212 }
1213 }
1214
1215 return fNbytes;
1216}
1217
1218////////////////////////////////////////////////////////////////////////////////
1219/// Decode input buffer.
1220///
1221/// In some situation will add key to gDirectory.
1222
1223void TKey::ReadBuffer(char *&buffer)
1224{
1225 ReadKeyBuffer(buffer);
1226
1227 if (!gROOT->ReadingObject() && gDirectory) {
1228 if (fSeekPdir != gDirectory->GetSeekDir()) gDirectory->AppendKey(this);
1229 }
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// Decode input buffer.
1234
1235void TKey::ReadKeyBuffer(char *&buffer)
1236{
1237 frombuf(buffer, &fNbytes);
1239 frombuf(buffer,&version);
1241 frombuf(buffer, &fObjlen);
1242 fDatime.ReadBuffer(buffer);
1243 frombuf(buffer, &fKeylen);
1244 frombuf(buffer, &fCycle);
1245 if (fVersion > 1000) {
1246 frombuf(buffer, &fSeekKey);
1247
1248 // We currently store in the 16 highest bit of fSeekPdir the value of
1249 // fPidOffset. This offset is used when a key (or basket) is transfered from one
1250 // file to the other. In this case the TRef and TObject might have stored a
1251 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1252 // file, the fPidOffset is to be added to those values to correctly find the
1253 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1254 // and need to be zero for new key/basket.
1255 Long64_t pdir;
1256 frombuf(buffer, &pdir);
1259 } else {
1261 frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey;
1263 }
1264 fClassName.ReadBuffer(buffer);
1265 //the following test required for forward and backward compatibility
1266 if (fClassName == "TDirectory") {
1267 fClassName = "TDirectoryFile";
1269 }
1270
1271 fName.ReadBuffer(buffer);
1272 fTitle.ReadBuffer(buffer);
1273}
1274
1275////////////////////////////////////////////////////////////////////////////////
1276/// Read the key structure from the file
1277
1279{
1280 TFile* f = GetFile();
1281 if (f==0) return kFALSE;
1282
1284 f->Seek(fSeekKey);
1285 if( f->ReadBuffer(fBuffer,nsize) )
1286 {
1287 Error("ReadFile", "Failed to read data.");
1288 return kFALSE;
1289 }
1290 if (gDebug) {
1291 std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
1292 }
1293 return kTRUE;
1294}
1295
1296////////////////////////////////////////////////////////////////////////////////
1297/// Set parent in key buffer.
1298
1299void TKey::SetParent(const TObject *parent)
1300{
1301 if (fBufferRef) fBufferRef->SetParent((TObject*)parent);
1302}
1303
1304////////////////////////////////////////////////////////////////////////////////
1305/// Reset the key as it had not been 'filled' yet.
1306
1308{
1309 fPidOffset = 0;
1310 fNbytes = 0;
1311 fBuffer = 0;
1312 fObjlen = 0;
1313 fCycle = 0;
1314 fSeekPdir = 0;
1315 fSeekKey = 0;
1316 fLeft = 0;
1317 fDatime = (UInt_t)0;
1318
1319 // fBufferRef and fKeylen intentionally not reset/changed
1320
1322}
1323
1324////////////////////////////////////////////////////////////////////////////////
1325/// Return the size in bytes of the key header structure.
1326///
1327/// An explanation about the nbytes (Int_t nbytes) variable used in the
1328/// function. The size of fSeekKey and fSeekPdir is 8 instead of 4 if version is
1329/// greater than 1000.
1330/// | Component | Sizeof |
1331/// |-------------------|------------|
1332/// | fNbytes | 4 |
1333/// | sizeof(Version_t) | 2 |
1334/// | fObjlen | 4 |
1335/// | fDatime | 4 |
1336/// | fKeylen | 2 |
1337/// | fCycle | 2 |
1338/// | fSeekKey | 4 or 8 |
1339/// | fSeekPdir | 4 or 8 |
1340/// | **FIXED TOTAL** | 26 or 34 |
1341/// | fClassName | 1+ bytes |
1342/// | fName | 1+ bytes |
1343/// | fTitle | 1+ bytes |
1344/// | **TOTAL** | 29+ or 37+ |
1345
1347{
1348 Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8;
1349 nbytes += fDatime.Sizeof();
1351 nbytes += 11; // strlen("TDirectory")+1
1352 } else {
1354 }
1355 nbytes += fName.Sizeof();
1356 nbytes += fTitle.Sizeof();
1357 return nbytes;
1358}
1359
1360////////////////////////////////////////////////////////////////////////////////
1361/// Stream a class object.
1362
1364{
1366 if (b.IsReading()) {
1367 b >> fNbytes;
1369 b >> fObjlen;
1371 b >> fKeylen;
1372 b >> fCycle;
1373 if (fVersion > 1000) {
1374 b >> fSeekKey;
1375
1376 // We currently store in the 16 highest bit of fSeekPdir the value of
1377 // fPidOffset. This offset is used when a key (or basket) is transfered from one
1378 // file to the other. In this case the TRef and TObject might have stored a
1379 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1380 // file, the fPidOffset is to be added to those values to correctly find the
1381 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1382 // and need to be zero for new key/basket.
1383 Long64_t pdir;
1384 b >> pdir;
1387 } else {
1391 }
1393 //the following test required for forward and backward compatibility
1394 if (fClassName == "TDirectory") {
1395 fClassName = "TDirectoryFile";
1397 }
1398 fName.Streamer(b);
1399 fTitle.Streamer(b);
1400 if (fKeylen < 0) {
1401 Error("Streamer","The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero",fKeylen);
1402 MakeZombie();
1403 fKeylen = 0;
1404 }
1405 if (fObjlen < 0) {
1406 Error("Streamer","The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero",fObjlen);
1407 MakeZombie();
1408 fObjlen = 0;
1409 }
1410 if (fNbytes < 0) {
1411 Error("Streamer","The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero",fNbytes);
1412 MakeZombie();
1413 fNbytes = 0;
1414 }
1415
1416 } else {
1417 b << fNbytes;
1419 b << version;
1420 b << fObjlen;
1421 if (fDatime.Get() == 0) fDatime.Set();
1423 TDatime((UInt_t) 1).Streamer(b);
1424 else
1426 b << fKeylen;
1427 b << fCycle;
1428 if (fVersion > 1000) {
1429 b << fSeekKey;
1430
1431 // We currently store in the 16 highest bit of fSeekPdir the value of
1432 // fPidOffset. This offset is used when a key (or basket) is transfered from one
1433 // file to the other. In this case the TRef and TObject might have stored a
1434 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1435 // file, the fPidOffset is to be added to those values to correctly find the
1436 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1437 // and need to be zero for new key/basket.
1439 b << pdir;
1440 } else {
1441 b << (Int_t)fSeekKey;
1442 b << (Int_t)fSeekPdir;
1443 }
1445 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
1446 b.WriteTString(gTDirectoryString);
1447 } else {
1449 }
1450 fName.Streamer(b);
1451 fTitle.Streamer(b);
1452 }
1453}
1454
1455////////////////////////////////////////////////////////////////////////////////
1456/// Write the encoded object supported by this key.
1457/// The function returns the number of bytes committed to the file.
1458/// If a write error occurs, the number of bytes returned is -1.
1459
1461{
1462 if (!f) f = GetFile();
1463 if (!f) return -1;
1464
1466 char *buffer = fBuffer;
1467 if (cycle) {
1468 fCycle = cycle;
1469 FillBuffer(buffer);
1470 buffer = fBuffer;
1471 }
1472
1473 if (fLeft > 0) nsize += sizeof(Int_t);
1474 f->Seek(fSeekKey);
1475 Bool_t result = f->WriteBuffer(buffer,nsize);
1476 //f->Flush(); Flushing takes too much time.
1477 // Let user flush the file when they want.
1478 if (gDebug) {
1479 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1480 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1481 }
1482
1483 DeleteBuffer();
1484 return result==kTRUE ? -1 : nsize;
1485}
1486
1487////////////////////////////////////////////////////////////////////////////////
1488/// Write the encoded object supported by this key.
1489/// The function returns the number of bytes committed to the file.
1490/// If a write error occurs, the number of bytes returned is -1.
1491
1493{
1494 if (!f) f = GetFile();
1495 if (!f) return -1;
1496
1498 char *buffer = fBuffer;
1499
1500 if (fLeft > 0) nsize += sizeof(Int_t);
1501 f->Seek(fSeekKey);
1502 Bool_t result = f->WriteBuffer(buffer,nsize);
1503 //f->Flush(); Flushing takes too much time.
1504 // Let user flush the file when they want.
1505 if (gDebug) {
1506 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1507 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1508 }
1509
1510 return result==kTRUE ? -1 : nsize;
1511}
1512
1513////////////////////////////////////////////////////////////////////////////////
1514/// Title can keep 32x32 xpm thumbnail/icon of the parent object.
1515
1516const char *TKey::GetIconName() const
1517{
1518 return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0);
1519}
1520
1521////////////////////////////////////////////////////////////////////////////////
1522/// Returns title (title can contain 32x32 xpm thumbnail/icon).
1523
1524const char *TKey::GetTitle() const
1525{
1526 if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) { // title contains xpm thumbnail
1527 static TString ret;
1528 int start = fTitle.Index("/*") + 3;
1529 int stop = fTitle.Index("*/") - 1;
1530 ret = fTitle(start, stop - start);
1531 return ret.Data();
1532 }
1533 return fTitle.Data();
1534}
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
#define ClassImp(name)
Definition Rtypes.h:376
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:270
@ 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:5018
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5440
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7593
@ kDummyNew
Definition TClass.h:110
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:5981
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4902
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2797
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition TClass.cxx:7491
@ kEmulated
Definition TClass.h:128
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2613
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:2974
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:240
void FillBuffer(char *&buffer)
Encode Date/Time into buffer, used by I/O system.
Definition TDatime.cxx:229
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).
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:1474
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:1524
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:541
@ 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:1346
TKey()
TKey default constructor.
Definition TKey.cxx:87
~TKey() override
TKey default destructor.
Definition TKey.cxx:528
TFile * GetFile() const
Returns file to which key belong.
Definition TKey.cxx:588
virtual void Keep()
Set the "KEEP" status.
Definition TKey.cxx:688
const char * GetIconName() const override
Title can keep 32x32 xpm thumbnail/icon of the parent object.
Definition TKey.cxx:1516
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:653
Short_t GetKeep() const
Returns the "KEEP" status.
Definition TKey.cxx:596
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:667
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:1278
void Browse(TBrowser *b) override
Read object from disk and call its Browse() method.
Definition TKey.cxx:430
virtual Int_t WriteFileKeepBuffer(TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1492
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:392
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:1299
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition TKey.cxx:1026
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1235
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:1307
Short_t fCycle
Cycle number.
Definition TKey.h:44
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition TKey.cxx:895
virtual void ls(Bool_t current) const
List Key contents.
Definition TKey.cxx:697
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:580
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:761
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
Definition TKey.cxx:462
virtual void DeleteBuffer()
Delete key buffer(s).
Definition TKey.cxx:562
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1460
virtual void ReadBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1223
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:717
void FillBuffer(char *&buffer) override
Encode key header into output buffer.
Definition TKey.cxx:604
void Streamer(TBuffer &) override
Stream a class object.
Definition TKey.cxx:1363
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:174
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:574
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:973
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:227
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1058
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:865
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1072
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1100
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:876
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:1046
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2899
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:1160
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:1317
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1419
virtual Int_t Sizeof() const
Returns size string will occupy on I/O buffer.
Definition TString.cxx:1408
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition TString.cxx:1338
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