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_files
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#include <limits>
53
54#include "TROOT.h"
55#include "TClass.h"
56#include "TDirectoryFile.h"
57#include "TFile.h"
58#include "TKey.h"
59#include "TBufferFile.h"
60#include "TFree.h"
61#include "TBrowser.h"
62#include "Bytes.h"
63#include "TInterpreter.h"
64#include "TError.h"
66#include "TSchemaRuleSet.h"
67#include "ThreadLocalStorage.h"
68
69#include "RZip.h"
70
71const Int_t kTitleMax = 32000;
72
73#if !defined(_MSC_VER) || (_MSC_VER>1300)
74const ULong64_t kPidOffsetMask = 0xffffffffffffULL;
75#else
76const ULong64_t kPidOffsetMask = 0xffffffffffffUL;
77#endif
79
80const static TString gTDirectoryString("TDirectory");
81std::atomic<UInt_t> keyAbsNumber{0};
82
83namespace {
84bool CheckKeyObjLenOverflow(const char *methodName, Int_t keyLen, Int_t objLen)
85{
86 constexpr auto maxInt_t = std::numeric_limits<Int_t>::max();
87 if (keyLen > (maxInt_t - objLen)) {
88 Error(methodName, "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.", objLen,
89 keyLen, maxInt_t);
90 return true;
91 }
92 return false;
93}
94} // namespace
95
96////////////////////////////////////////////////////////////////////////////////
97/// TKey default constructor.
98
99TKey::TKey() : TNamed(), fDatime((UInt_t)0)
100{
101 Build(0, "", 0);
102
103 fKeylen = Sizeof();
104
106}
107
108////////////////////////////////////////////////////////////////////////////////
109/// TKey default constructor.
110
111TKey::TKey(TDirectory* motherDir) : TNamed(), fDatime((UInt_t)0)
112{
113 Build(motherDir, "", 0);
114
115 fKeylen = Sizeof();
116
118}
119
120////////////////////////////////////////////////////////////////////////////////
121/// Copy a TKey from its original directory to the new 'motherDir'
122
123TKey::TKey(TDirectory* motherDir, const TKey &orig, UShort_t pidOffset) : TNamed(), fDatime((UInt_t)0)
124{
125 fMotherDir = motherDir;
126
127 fPidOffset = orig.fPidOffset + pidOffset;
128 fNbytes = orig.fNbytes;
129 fObjlen = orig.fObjlen;
130 fClassName = orig.fClassName;
131 fName = orig.fName;
132 fTitle = orig.fTitle;
133
134 fCycle = fMotherDir->AppendKey(this);
135 fSeekPdir = 0;
136 fSeekKey = 0;
137 fLeft = 0;
138
140 Long64_t filepos = GetFile()->GetEND();
141 if (filepos > TFile::kStartBigFile || fPidOffset) fVersion += 1000;
142
143 fKeylen = Sizeof(); // fVersion must be set.
144
145 UInt_t bufferDecOffset = 0;
146 UInt_t bufferIncOffset = 0;
147 UInt_t alloc = fNbytes + sizeof(Int_t); // The extra Int_t is for any free space information.
148 if (fKeylen < orig.fKeylen) {
149 bufferDecOffset = orig.fKeylen - fKeylen;
150 fNbytes -= bufferDecOffset;
151 } else if (fKeylen > orig.fKeylen) {
152 bufferIncOffset = fKeylen - orig.fKeylen;
153 alloc += bufferIncOffset;
154 fNbytes += bufferIncOffset;
155 }
156
159
160 // Steal the data from the old key.
161
162 TFile* f = orig.GetFile();
163 if (f) {
164 Int_t nsize = orig.fNbytes;
165 f->Seek(orig.fSeekKey);
166 if( f->ReadBuffer(fBuffer+bufferIncOffset,nsize) )
167 {
168 Error("ReadFile", "Failed to read data.");
169 return;
170 }
171 if (gDebug) {
172 std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
173 }
174 }
175 fBuffer += bufferDecOffset; // Reset the buffer to be appropriate for this key.
176 Int_t nout = fNbytes - fKeylen;
177 Create(nout);
178 fBufferRef->SetBufferOffset(bufferDecOffset);
179 Streamer(*fBufferRef); //write key itself again
180}
181
182////////////////////////////////////////////////////////////////////////////////
183/// Create a TKey object to read keys.
184/// Constructor called by TDirectoryFile::ReadKeys and by TFile::TFile.
185/// A TKey object is created to read the keys structure itself.
186
187TKey::TKey(Long64_t pointer, Int_t nbytes, TDirectory* motherDir) : TNamed()
188{
189 Build(motherDir, "", pointer);
190
191 fSeekKey = pointer;
192 fNbytes = nbytes;
193 fBuffer = new char[nbytes];
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Create a TKey object with the specified name, title for the given class.
199///
200/// WARNING: in name avoid special characters like '^','$','.' that are used
201/// by the regular expression parser (see TRegexp).
202
203TKey::TKey(const char *name, const char *title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
204 : TNamed(name,title)
205{
206 Build(motherDir, cl->GetName(), -1);
207
208 fKeylen = Sizeof();
209 fObjlen = nbytes;
210 Create(nbytes);
211}
212
213////////////////////////////////////////////////////////////////////////////////
214/// Create a TKey object with the specified name, title for the given class.
215///
216/// WARNING: in name avoid special characters like '^','$','.' that are used
217/// by the regular expression parser (see TRegexp).
218
219TKey::TKey(const TString &name, const TString &title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
220 : TNamed(name,title)
221{
222 Build(motherDir, cl->GetName(), -1);
223
224 fKeylen = Sizeof();
225 fObjlen = nbytes;
226 Create(nbytes);
227}
228
229////////////////////////////////////////////////////////////////////////////////
230/// Create a TKey object for a TObject* and fill output buffer
231///
232/// WARNING: in name avoid special characters like '^','$','.' that are used
233/// by the regular expression parser (see TRegexp).
234
235TKey::TKey(const TObject *obj, const char *name, Int_t bufsize, TDirectory* motherDir)
236 : TNamed(name, obj->GetTitle())
237{
238 R__ASSERT(obj);
239
240 if (!obj->IsA()->HasDefaultConstructor()) {
241 Warning("TKey", "since %s has no public constructor\n"
242 "\twhich can be called without argument, objects of this class\n"
243 "\tcan not be read with the current library. You will need to\n"
244 "\tadd a default constructor before attempting to read it.",
245 obj->ClassName());
246 }
247
248 Build(motherDir, obj->ClassName(), -1);
249
250 Int_t lbuf, nout, noutot, bufmax, nzip;
251 fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize);
253 fCycle = fMotherDir->AppendKey(this);
254
255 Streamer(*fBufferRef); //write key itself
257 fBufferRef->MapObject(obj); //register obj in map in case of self reference
258 ((TObject*)obj)->Streamer(*fBufferRef); //write object
259 lbuf = fBufferRef->Length();
260 fObjlen = lbuf - fKeylen;
261
262 Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0;
264 if (cxlevel > 0 && fObjlen > 256) {
265 const auto blocks = ROOT::Internal::GetZipBlocks(fObjlen);
266 const Int_t nbuffers = blocks.fNBlocks;
267 const Int_t blockSize = blocks.fBlockSize;
268 Int_t buflen = std::max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
269 fBuffer = new char[buflen];
270 char *objbuf = fBufferRef->Buffer() + fKeylen;
271 char *bufcur = &fBuffer[fKeylen];
272 noutot = 0;
273 nzip = 0;
274 for (Int_t i = 0; i < nbuffers; ++i) {
275 if (i == nbuffers - 1)
276 bufmax = fObjlen - nzip;
277 else
278 bufmax = blockSize;
279 R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
280 if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
281 delete[] fBuffer;
282 bufcur = nullptr;
286 Streamer(*fBufferRef); //write key itself again
287 return;
288 }
289 bufcur += nout;
290 noutot += nout;
291 objbuf += blockSize;
292 nzip += blockSize;
293 }
294 Create(noutot);
296 Streamer(*fBufferRef); //write key itself again
297 memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
298 delete fBufferRef; fBufferRef = 0;
299 } else {
303 Streamer(*fBufferRef); //write key itself again
304 }
305}
306
307////////////////////////////////////////////////////////////////////////////////
308/// Create a TKey object for any object obj of class cl d and fill
309/// output buffer.
310///
311/// WARNING: in name avoid special characters like '^','$','.' that are used
312/// by the regular expression parser (see TRegexp).
313
314TKey::TKey(const void *obj, const TClass *cl, const char *name, Int_t bufsize, TDirectory *motherDir) : TNamed(name, "")
315{
316 R__ASSERT(obj && cl);
317
318 if (!cl->HasDefaultConstructor()) {
319 Warning("TKey", "since %s has no public constructor\n"
320 "\twhich can be called without argument, objects of this class\n"
321 "\tcan not be read with the current library. You will need to\n"
322 "\tadd a default constructor before attempting to read it.",
323 cl->GetName());
324 }
325
326 TClass *clActual = cl->GetActualClass(obj);
327 const void* actualStart;
328 if (clActual) {
329 const char *temp = (const char*) obj;
330 // clActual->GetStreamerInfo();
331 Int_t offset = (cl != clActual) ?
332 clActual->GetBaseClassOffset(cl) : 0;
333 temp -= offset;
334 actualStart = temp;
335 } else {
336 // We could not determine the real type of this object,
337 // let's assume it is the one given by the caller.
338 clActual = const_cast<TClass*>(cl);
339 actualStart = obj;
340 }
341
342 Build(motherDir, clActual->GetName(), -1);
343
344 fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize);
346
347 Streamer(*fBufferRef); //write key itself
349
350 Int_t lbuf, nout, noutot, bufmax, nzip;
351
352 fBufferRef->MapObject(actualStart,clActual); //register obj in map in case of self reference
353 clActual->Streamer((void*)actualStart, *fBufferRef); //write object
354 lbuf = fBufferRef->Length();
355 fObjlen = lbuf - fKeylen;
356
357 // Append to mother directory only after the call to Streamer() was
358 // successful (and didn't throw).
359 fCycle = fMotherDir->AppendKey(this);
360
361 Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0;
363 if (cxlevel > 0 && fObjlen > 256) {
364 const auto blocks = ROOT::Internal::GetZipBlocks(fObjlen);
365 const Int_t nbuffers = blocks.fNBlocks;
366 const Int_t blockSize = blocks.fBlockSize;
367 Int_t buflen = std::max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
368 fBuffer = new char[buflen];
369 char *objbuf = fBufferRef->Buffer() + fKeylen;
370 char *bufcur = &fBuffer[fKeylen];
371 noutot = 0;
372 nzip = 0;
373 for (Int_t i = 0; i < nbuffers; ++i) {
374 if (i == nbuffers - 1)
375 bufmax = fObjlen - nzip;
376 else
377 bufmax = blockSize;
378 R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
379 if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
380 delete[] fBuffer;
381 bufcur = nullptr;
385 Streamer(*fBufferRef); //write key itself again
386 return;
387 }
388 bufcur += nout;
389 noutot += nout;
390 objbuf += blockSize;
391 nzip += blockSize;
392 }
393 Create(noutot);
395 Streamer(*fBufferRef); //write key itself again
396 memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
397 delete fBufferRef; fBufferRef = 0;
398 } else {
402 Streamer(*fBufferRef); //write key itself again
403 }
404}
405
406/// Core of uncompressing the key payload. Returns number of bytes uncompressed.
407/// We expect that the compressedBuffer contains the entire key (key header + payload).
408/// The target buffer must have space for at least fObjLen bytes.
409/// Lastly, the object length must be larger than the key payload, i.e. we already know that
410/// we have a compressed payload.
411Int_t TKey::UnzipBuffer(char *targetBuffer, const char *compressedBuffer) const
412{
413 auto objbuf = reinterpret_cast<unsigned char *>(targetBuffer) + fKeylen;
414 auto bufcur = reinterpret_cast<const unsigned char *>(&compressedBuffer[fKeylen]);
415 Int_t nin, nout = 0, nbuf;
416 Int_t noutot = 0;
417 Int_t nbytesRemain = fNbytes - fKeylen;
418 Int_t objlenRemain = fObjlen;
419 while (nbytesRemain >= ROOT::Internal::kZipHeaderSize) {
420 Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
421 if ((hc != 0) || (nin > nbytesRemain) || (nbuf > objlenRemain))
422 return 0;
423 R__unzip(&nin, bufcur, &nbuf, objbuf, &nout);
424 if (!nout)
425 return 0;
426 noutot += nout;
427 if (noutot >= fObjlen)
428 break;
429 bufcur += nin;
430 objbuf += nout;
431 nbytesRemain -= nin;
432 objlenRemain -= nout;
433 }
434 return nout;
435}
436
437////////////////////////////////////////////////////////////////////////////////
438/// Method used in all TKey constructor to initialize basic data fields.
439///
440/// The member filepos is used to calculate correct version number of key
441/// if filepos==-1, end of file position is used.
442
443void TKey::Build(TDirectory* motherDir, const char* classname, Long64_t filepos)
444{
445 fMotherDir = motherDir;
446
447 fPidOffset = 0;
448 fNbytes = 0;
449 fBuffer = 0;
450 fKeylen = 0;
451 fObjlen = 0;
452 fBufferRef = 0;
453 fCycle = 0;
454 fSeekPdir = 0;
455 fSeekKey = 0;
456 fLeft = 0;
457
458 fClassName = classname;
459 //the following test required for forward and backward compatibility
460 if (fClassName == "TDirectoryFile") SetBit(kIsDirectoryFile);
461
463
464 if ((filepos==-1) && GetFile()) filepos = GetFile()->GetEND();
465 if (filepos > TFile::kStartBigFile) fVersion += 1000;
466
468
471}
472
473////////////////////////////////////////////////////////////////////////////////
474/// Read object from disk and call its Browse() method.
475///
476/// If object with same name already exist in memory delete it (like
477/// TDirectoryFile::Get() is doing), except when the key references a
478/// folder in which case we don't want to re-read the folder object
479/// since it might contain new objects not yet saved.
480
482{
483 if (fMotherDir==0) return;
484
486
487 void* obj = fMotherDir->GetList()->FindObject(GetName());
488 if (obj && objcl->IsTObject()) {
489 TObject *tobj = (TObject*) objcl->DynamicCast(TObject::Class(), obj);
490 if (!tobj->IsFolder()) {
491 if (tobj->InheritsFrom(TCollection::Class()))
492 tobj->Delete(); // delete also collection elements
493 delete tobj;
494 obj = 0;
495 }
496 }
497
498 if (!obj)
499 obj = ReadObj();
500
501 if (b && obj) {
502 objcl->Browse(obj,b);
503 b->SetRefreshFlag(kTRUE);
504 }
505}
506
507////////////////////////////////////////////////////////////////////////////////
508/// Create a TKey object of specified size.
509///
510/// If externFile!=0, key will be allocated in specified file, otherwise file
511/// of mother directory will be used.
512
513void TKey::Create(Int_t nbytes, TFile* externFile)
514{
516
517 TFile *f = externFile;
518 if (!f) f = GetFile();
519 if (!f) {
520 Error("Create","Cannot create key without file");
521 return;
522 }
523
524 Int_t nsize = nbytes + fKeylen;
525 TList *lfree = f->GetListOfFree();
526 TFree *f1 = (TFree*)lfree->First();
527//*-*-------------------find free segment
528//*-* =================
529 TFree *bestfree = f1->GetBestFree(lfree,nsize);
530 if (bestfree == 0) {
531 Error("Create","Cannot allocate %d bytes for ID = %s Title = %s",
532 nsize,GetName(),GetTitle());
533 return;
534 }
535
536 if (f->TestBit(TFile::kReproducible))
538
539 fDatime.Set();
540 fSeekKey = bestfree->GetFirst();
541//*-*----------------- Case Add at the end of the file
542 if (fSeekKey >= f->GetEND()) {
543 f->SetEND(fSeekKey+nsize);
544 bestfree->SetFirst(fSeekKey+nsize);
545 if (f->GetEND() > bestfree->GetLast()) {
546 bestfree->SetLast(bestfree->GetLast() + 1000000000);
547 }
548 fLeft = -1;
549 if (!fBuffer) fBuffer = new char[nsize];
550 } else {
551 fLeft = Int_t(bestfree->GetLast() - fSeekKey - nsize + 1);
552 }
553//*-*----------------- Case where new object fills exactly a deleted gap
554 fNbytes = nsize;
555 if (fLeft == 0) {
556 if (!fBuffer) {
557 fBuffer = new char[nsize];
558 }
559 lfree->Remove(bestfree);
560 delete bestfree;
561 }
562//*-*----------------- Case where new object is placed in a deleted gap larger than itself
563 if (fLeft > 0) { // found a bigger segment
564 if (!fBuffer) {
565 fBuffer = new char[nsize+sizeof(Int_t)];
566 }
567 char *buffer = fBuffer+nsize;
568 Int_t nbytesleft = -fLeft; // set header of remaining record
569 tobuf(buffer, nbytesleft);
570 bestfree->SetFirst(fSeekKey+nsize);
571 }
572
573 fSeekPdir = externFile ? externFile->GetSeekDir() : fMotherDir->GetSeekDir();
574}
575
576////////////////////////////////////////////////////////////////////////////////
577/// TKey default destructor.
578
585
586////////////////////////////////////////////////////////////////////////////////
587/// Delete an object from the file.
588///
589/// Note: the key is not deleted. You still have to call "delete key".
590/// This is different from the behaviour of TObject::Delete()!
591
593{
595 // TDirectoryFile assumes that its location on file never change (for example updates are partial)
596 // and never checks if the space might have been released and thus over-write any data that might
597 // have been written there.
598 if (option && option[0] == 'v')
599 printf("Rejected attempt to delete TDirectoryFile key: %s at address %lld, nbytes = %d\n",
601 return;
602 }
603 if (option && option[0] == 'v') printf("Deleting key: %s at address %lld, nbytes = %d\n",GetName(),fSeekKey,fNbytes);
604 Long64_t first = fSeekKey;
605 Long64_t last = fSeekKey + fNbytes -1;
606 if (GetFile()) GetFile()->MakeFree(first, last); // release space used by this key
608}
609
610////////////////////////////////////////////////////////////////////////////////
611/// Delete key buffer(s).
612
614{
615 if (fBufferRef) {
616 delete fBufferRef;
617 fBufferRef = 0;
618 } else {
619 // We only need to delete fBuffer if fBufferRef is zero because
620 // if fBufferRef exists, we delegate ownership of fBuffer to fBufferRef.
621 if (fBuffer) {
622 delete [] fBuffer;
623 }
624 }
625 fBuffer = 0;
626}
627
628////////////////////////////////////////////////////////////////////////////////
629/// Return cycle number associated to this key.
630
632{
633 return ((fCycle >0) ? fCycle : -fCycle);
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// Returns file to which key belong.
638
640{
641 return fMotherDir!=0 ? fMotherDir->GetFile() : gFile;
642}
643
644////////////////////////////////////////////////////////////////////////////////
645/// Returns the "KEEP" status.
646
648{
649 return ((fCycle >0) ? 0 : 1);
650}
651
652////////////////////////////////////////////////////////////////////////////////
653/// Encode key header into output buffer.
654
655void TKey::FillBuffer(char *&buffer)
656{
657 tobuf(buffer, fNbytes);
658 Version_t version = fVersion;
659 tobuf(buffer, version);
660
661 tobuf(buffer, fObjlen);
663 TDatime((UInt_t) 1).FillBuffer(buffer);
664 else
665 fDatime.FillBuffer(buffer);
666 tobuf(buffer, fKeylen);
667 tobuf(buffer, fCycle);
668 if (fVersion > 1000) {
669 tobuf(buffer, fSeekKey);
670
671 // We currently store in the 16 highest bit of fSeekPdir the value of
672 // fPidOffset. This offset is used when a key (or basket) is transferred from one
673 // file to the other. In this case the TRef and TObject might have stored a
674 // pid index (to retrieve TProcessIDs) which refered to their order on the original
675 // file, the fPidOffset is to be added to those values to correctly find the
676 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
677 // and need to be zero for new key/basket.
679 tobuf(buffer, pdir);
680 } else {
681 tobuf(buffer, (Int_t)fSeekKey);
682 tobuf(buffer, (Int_t)fSeekPdir);
683 }
685 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
687 } else {
688 fClassName.FillBuffer(buffer);
689 }
690 fName.FillBuffer(buffer);
691 fTitle.FillBuffer(buffer);
692}
693
694////////////////////////////////////////////////////////////////////////////////
695/// Increment fPidOffset by 'offset'.
696///
697/// This offset is used when a key (or basket) is transferred from one file to
698/// the other. In this case the TRef and TObject might have stored a pid
699/// index (to retrieve TProcessIDs) which refered to their order on the
700/// original file, the fPidOffset is to be added to those values to correctly
701/// find the TProcessID. This fPidOffset needs to be increment if the
702/// key/basket is copied and need to be zero for new key/basket.
703
705{
707 if (fPidOffset) {
708 // We currently store fPidOffset in the 16 highest bit of fSeekPdir, which
709 // need to be store as a 64 bit integer. So we require this key to be
710 // a 'large file' key.
711 if (fVersion<1000) fVersion += 1000;
712 }
713}
714
715////////////////////////////////////////////////////////////////////////////////
716/// Check if object referenced by the key is a folder.
717
719{
720 Bool_t ret = kFALSE;
721
722 TClass *classPtr = TClass::GetClass((const char *) fClassName);
723 if (classPtr && classPtr->GetState() > TClass::kEmulated && classPtr->IsTObject()) {
724 TObject *obj = (TObject *) classPtr->DynamicCast(TObject::Class(), classPtr->New(TClass::kDummyNew));
725 if (obj) {
726 ret = obj->IsFolder();
727 delete obj;
728 }
729 }
730
731 return ret;
732}
733
734////////////////////////////////////////////////////////////////////////////////
735/// Set the "KEEP" status.
736///
737/// When the KEEP flag is set to 1 the object cannot be purged.
738
740{
741 if (fCycle >0) fCycle = -fCycle;
742}
743
744////////////////////////////////////////////////////////////////////////////////
745/// List Key contents.
746/// Add indicator of whether it is the current item or a backup copy.
747
748void TKey::ls(Bool_t current) const
749{
751 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle();
752 std::cout << (current ? " [current cycle]" : " [backup cycle]");
753 std::cout <<std::endl;
754}
755
756////////////////////////////////////////////////////////////////////////////////
757/// List Key contents.
758
759void TKey::ls(Option_t *) const
760{
762 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<std::endl;
763}
764
765////////////////////////////////////////////////////////////////////////////////
766/// Print key contents.
767
769{
770 printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle());
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// To read a TObject* from the file.
775///
776/// The object associated to this key is read from the file into memory
777/// Once the key structure is read (via Streamer) the class identifier
778/// of the object is known.
779/// Using the class identifier we find the TClass object for this class.
780/// A TClass object contains a full description (i.e. dictionary) of the
781/// associated class. In particular the TClass object can create a new
782/// object of the class type it describes. This new object now calls its
783/// Streamer function to rebuilt itself.
784///
785/// Use TKey::ReadObjectAny to read any object non-derived from TObject
786///
787/// ### Note
788/// A C style cast can only be used in the case where the final class
789/// of this object derives from TObject as a first inheritance, otherwise
790/// one must use a dynamic_cast.
791///
792/// #### Example1: simplified case
793/// ~~~{.cpp}
794/// class MyClass : public TObject, public AnotherClass
795/// ~~~
796/// then on return, one get away with using:
797/// ~~~{.cpp}
798/// MyClass *obj = (MyClass*)key->ReadObj();
799/// ~~~
800///
801/// #### Example2: Usual case (recommended unless performance is critical)
802/// ~~~{.cpp}
803/// MyClass *obj = dynamic_cast<MyClass*>(key->ReadObj());
804/// ~~~
805/// which support also the more complex inheritance like:
806/// ~~~{.cpp}
807/// class MyClass : public AnotherClass, public TObject
808/// ~~~
809///
810/// Of course, `dynamic_cast<>` can also be used in the example 1.
811
813{
815 if (!cl) {
816 Error("ReadObj", "Unknown class %s", fClassName.Data());
817 return 0;
818 }
819 if (!cl->IsTObject()) {
820 // in principle user should call TKey::ReadObjectAny!
821 return (TObject*)ReadObjectAny(0);
822 }
823
825 if (!bufferRef.Buffer()) {
826 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
827 return 0;
828 }
829 if (GetFile()==0) return 0;
830 bufferRef.SetParent(GetFile());
831 bufferRef.SetPidOffset(fPidOffset);
832
833 std::unique_ptr<char []> compressedBuffer;
834 auto storeBuffer = fBuffer;
835 if (fObjlen > fNbytes-fKeylen) {
836 compressedBuffer.reset(new char[fNbytes]);
837 fBuffer = compressedBuffer.get();
838 if( !ReadFile() ) //Read object structure from file
839 {
840 fBuffer = 0;
841 return 0;
842 }
843 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
844 } else {
845 fBuffer = bufferRef.Buffer();
846 if( !ReadFile() ) { //Read object structure from file
847
848 fBuffer = 0;
849 return 0;
850 }
851 }
852 fBuffer = storeBuffer;
853
854 // get version of key
855 bufferRef.SetBufferOffset(sizeof(fNbytes));
856 Version_t kvers = bufferRef.ReadVersion();
857
858 bufferRef.SetBufferOffset(fKeylen);
859 TObject *tobj = 0;
860 // Create an instance of this class
861
862 char *pobj = (char*)cl->New();
863 if (!pobj) {
864 Error("ReadObj", "Cannot create new object of class %s", fClassName.Data());
865 return 0;
866 }
867 Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
868 if (baseOffset==-1) {
869 // cl does not inherit from TObject.
870 // Since this is not possible yet, the only reason we could reach this code
871 // is because something is screw up in the ROOT code.
872 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
873 fClassName.Data());
874 }
875 tobj = (TObject*)(pobj+baseOffset);
876 if (kvers > 1)
877 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
878
879 if (fObjlen > fNbytes-fKeylen) {
880 Int_t nout = UnzipBuffer(bufferRef.Buffer(), compressedBuffer.get());
881 compressedBuffer.reset(nullptr);
882 if (nout) {
883 tobj->Streamer(bufferRef); //does not work with example 2 above
884 } else {
885 // Even-though we have a TObject, if the class is emulated the virtual
886 // table may not be 'right', so let's go via the TClass.
887 cl->Destructor(pobj);
888 return nullptr;
889 }
890 } else {
891 tobj->Streamer(bufferRef);
892 }
893
894 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
895
897 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
898 dir->SetName(GetName());
899 dir->SetTitle(GetTitle());
900 dir->SetMother(fMotherDir);
901 fMotherDir->Append(dir);
902 }
903
904 // Append the object to the directory if requested:
905 {
907 if (addfunc) {
908 addfunc(pobj, fMotherDir);
909 }
910 }
911
912 return tobj;
913}
914
915////////////////////////////////////////////////////////////////////////////////
916/// To read a TObject* from bufferRead.
917///
918/// This function is identical to TKey::ReadObj, but it reads directly from
919/// bufferRead instead of reading from a file.
920/// The object associated to this key is read from the buffer into memory
921/// Using the class identifier we find the TClass object for this class.
922/// A TClass object contains a full description (i.e. dictionary) of the
923/// associated class. In particular the TClass object can create a new
924/// object of the class type it describes. This new object now calls its
925/// Streamer function to rebuilt itself.
926///
927/// ### Note
928/// This function is called only internally by ROOT classes.
929/// Although being public it is not supposed to be used outside ROOT.
930/// If used, you must make sure that the bufferRead is large enough to
931/// accommodate the object being read.
932
934{
935
937 if (!cl) {
938 Error("ReadObjWithBuffer", "Unknown class %s", fClassName.Data());
939 return 0;
940 }
941 if (!cl->IsTObject()) {
942 // in principle user should call TKey::ReadObjectAny!
943 return (TObject*)ReadObjectAny(0);
944 }
945
947 if (!bufferRef.Buffer()) {
948 Error("ReadObjWithBuffer", "Cannot allocate buffer: fObjlen = %d", fObjlen);
949 return 0;
950 }
951 if (GetFile()==0) return 0;
952 bufferRef.SetParent(GetFile());
953 bufferRef.SetPidOffset(fPidOffset);
954
955 auto storeBuffer = fBuffer;
956 if (fObjlen > fNbytes-fKeylen) {
957 fBuffer = bufferRead;
958 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
959 } else {
960 fBuffer = bufferRef.Buffer();
961 ReadFile(); //Read object structure from file
962 }
963 fBuffer = storeBuffer;
964
965 // get version of key
966 bufferRef.SetBufferOffset(sizeof(fNbytes));
967 Version_t kvers = bufferRef.ReadVersion();
968
969 bufferRef.SetBufferOffset(fKeylen);
970 TObject *tobj = 0;
971 // Create an instance of this class
972
973 char *pobj = (char*)cl->New();
974 if (!pobj) {
975 Error("ReadObjWithBuffer", "Cannot create new object of class %s", fClassName.Data());
976 return 0;
977 }
978 Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
979 if (baseOffset==-1) {
980 // cl does not inherit from TObject.
981 // Since this is not possible yet, the only reason we could reach this code
982 // is because something is screw up in the ROOT code.
983 Fatal("ReadObjWithBuffer","Incorrect detection of the inheritance from TObject for class %s.\n",
984 fClassName.Data());
985 }
986 tobj = (TObject*)(pobj+baseOffset);
987
988 if (kvers > 1)
989 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
990
991 if (fObjlen > fNbytes-fKeylen) {
992 Int_t nout = UnzipBuffer(bufferRef.Buffer(), bufferRead);
993 if (nout) {
994 tobj->Streamer(bufferRef); //does not work with example 2 above
995 } else {
996 // Even-though we have a TObject, if the class is emulated the virtual
997 // table may not be 'right', so let's go via the TClass.
998 cl->Destructor(pobj);
999 return nullptr;
1000 }
1001 } else {
1002 tobj->Streamer(bufferRef);
1003 }
1004
1005 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
1006
1008 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1009 dir->SetName(GetName());
1010 dir->SetTitle(GetTitle());
1011 dir->SetMother(fMotherDir);
1012 fMotherDir->Append(dir);
1013 }
1014
1015 // Append the object to the directory if requested:
1016 {
1018 if (addfunc) {
1019 addfunc(pobj, fMotherDir);
1020 }
1021 }
1022
1023 return tobj;
1024}
1025
1026////////////////////////////////////////////////////////////////////////////////
1027/// To read an object (non deriving from TObject) from the file.
1028///
1029/// If expectedClass is not null, we checked that that actual class of the
1030/// object stored is suitable to be stored in a pointer pointing to an object
1031/// of class 'expectedClass'. We also adjust the value of the returned address
1032/// so that it is suitable to be cast (C-Style)
1033/// a pointer pointing to an object of class 'expectedClass'.
1034///
1035/// So for example if the class Bottom inherits from Top and the object
1036/// stored is of type Bottom you can safely do:
1037/// ~~~{.cpp}
1038/// auto TopClass = TClass::GetClass("Top");
1039/// auto ptr = (Top*) key->ReadObjectAny( TopClass );
1040/// if (ptr==0) printError("the object stored in the key is not of the expected type\n");
1041/// ~~~
1042/// The object associated to this key is read from the file into memory.
1043/// Once the key structure is read (via Streamer) the class identifier
1044/// of the object is known.
1045/// Using the class identifier we find the TClass object for this class.
1046/// A TClass object contains a full description (i.e. dictionary) of the
1047/// associated class. In particular the TClass object can create a new
1048/// object of the class type it describes. This new object now calls its
1049/// Streamer function to rebuilt itself.
1050
1051void *TKey::ReadObjectAny(const TClass* expectedClass)
1052{
1054 if (!bufferRef.Buffer()) {
1055 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
1056 return 0;
1057 }
1058 if (GetFile()==0) return 0;
1059 bufferRef.SetParent(GetFile());
1060 bufferRef.SetPidOffset(fPidOffset);
1061
1062 std::unique_ptr<char []> compressedBuffer;
1063 auto storeBuffer = fBuffer;
1064 if (fObjlen > fNbytes-fKeylen) {
1065 compressedBuffer.reset(new char[fNbytes]);
1066 fBuffer = compressedBuffer.get();
1067 ReadFile(); //Read object structure from file
1068 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1069 } else {
1070 fBuffer = bufferRef.Buffer();
1071 ReadFile(); //Read object structure from file
1072 }
1073 fBuffer = storeBuffer;
1074
1075 // get version of key
1076 bufferRef.SetBufferOffset(sizeof(fNbytes));
1077 Version_t kvers = bufferRef.ReadVersion();
1078
1079 bufferRef.SetBufferOffset(fKeylen);
1081 TClass *clOnfile = 0;
1082 if (!cl) {
1083 Error("ReadObjectAny", "Unknown class %s", fClassName.Data());
1084 return 0;
1085 }
1086 Int_t baseOffset = 0;
1087 if (expectedClass) {
1088 // baseOffset will be -1 if cl does not inherit from expectedClass
1089 baseOffset = cl->GetBaseClassOffset(expectedClass);
1090 if (baseOffset == -1) {
1091 // The 2 classes are unrelated, maybe there is a converter between the 2.
1092
1093 if (!expectedClass->GetSchemaRules() ||
1094 !expectedClass->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()))
1095 {
1096 // There is no converter
1097 return 0;
1098 }
1099 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 ....
1100 clOnfile = cl;
1101 cl = const_cast<TClass*>(expectedClass);
1102 if (gDebug > 0)
1103 Info("ReadObjectAny", "Using Converter StreamerInfo from %s to %s", clOnfile->GetName(),
1104 expectedClass->GetName());
1105 }
1106 if (cl->GetState() > TClass::kEmulated && expectedClass->GetState() <= TClass::kEmulated) {
1107 //we cannot mix a compiled class with an emulated class in the inheritance
1108 Warning("ReadObjectAny",
1109 "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
1110 cl->GetName(),expectedClass->GetName());
1111 }
1112 }
1113 // Create an instance of this class
1114
1115 void *pobj = cl->New();
1116 if (!pobj) {
1117 Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data());
1118 return 0;
1119 }
1120
1121 if (kvers > 1)
1122 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
1123
1124 if (fObjlen > fNbytes-fKeylen) {
1125 Int_t nout = UnzipBuffer(bufferRef.Buffer(), compressedBuffer.get());
1126 if (nout) {
1127 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1128 } else {
1129 cl->Destructor(pobj);
1130 return nullptr;
1131 }
1132 } else {
1133 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1134 }
1135
1136 if (cl->IsTObject()) {
1137 auto tobjBaseOffset = cl->GetBaseClassOffset(TObject::Class());
1138 if (tobjBaseOffset == -1) {
1139 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
1140 fClassName.Data());
1141 }
1142 TObject *tobj = (TObject*)( ((char*)pobj) + tobjBaseOffset);
1143
1144 // See similar adjustments in ReadObj
1145 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
1146
1148 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1149 dir->SetName(GetName());
1150 dir->SetTitle(GetTitle());
1151 dir->SetMother(fMotherDir);
1152 fMotherDir->Append(dir);
1153 }
1154 }
1155
1156 {
1157 // Append the object to the directory if requested:
1159 if (addfunc) {
1160 addfunc(pobj, fMotherDir);
1161 }
1162 }
1163
1164 return ( ((char*)pobj) + baseOffset );
1165}
1166
1167////////////////////////////////////////////////////////////////////////////////
1168/// To read an object from the file.
1169///
1170/// The object associated to this key is read from the file into memory.
1171/// Before invoking this function, obj has been created via the
1172/// default constructor.
1173
1175{
1176 if (!obj || (GetFile()==0)) return 0;
1177
1179 bufferRef.SetParent(GetFile());
1180 bufferRef.SetPidOffset(fPidOffset);
1181
1182 if (fVersion > 1)
1183 bufferRef.MapObject(obj); //register obj in map to handle self reference
1184
1185 std::unique_ptr<char []> compressedBuffer;
1186 auto storeBuffer = fBuffer;
1187 if (fObjlen > fNbytes-fKeylen) {
1188 compressedBuffer.reset(new char[fNbytes]);
1189 fBuffer = compressedBuffer.get();
1190 ReadFile(); //Read object structure from file
1191 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1192 } else {
1193 fBuffer = bufferRef.Buffer();
1194 ReadFile(); //Read object structure from file
1195 }
1196 fBuffer = storeBuffer;
1197
1198 bufferRef.SetBufferOffset(fKeylen);
1199 if (fObjlen > fNbytes-fKeylen) {
1200 Int_t nout = UnzipBuffer(bufferRef.Buffer(), compressedBuffer.get());
1201 if (nout)
1202 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);
1238 if (fNbytes < 0) {
1239 Error("ReadKeyBuffer", "The value of fNbytes is negative (%d): cannot continue to read the key buffer.", fNbytes);
1240 MakeZombie();
1241 fNbytes = 0;
1242 return;
1243 }
1244 Version_t version;
1245 frombuf(buffer,&version);
1246 fVersion = (Int_t)version;
1247 frombuf(buffer, &fObjlen);
1248 if (fObjlen < 0) {
1249 Error("ReadKeyBuffer", "The value of fObjlen is negative (%d): cannot continue to read the key buffer.", fObjlen);
1250 MakeZombie();
1251 fObjlen = 0;
1252 return;
1253 }
1254 fDatime.ReadBuffer(buffer);
1255 frombuf(buffer, &fKeylen);
1256 if (fKeylen < 0) {
1257 Error("ReadKeyBuffer", "The value of fKeylen is negative (%d): cannot continue to read the key buffer.", fKeylen);
1258 MakeZombie();
1259 fKeylen = 0;
1260 return;
1261 }
1262
1263 if (fNbytes < fKeylen) {
1264 Error("ReadKeyBuffer", "fNbytes (%d) < fKeylen (%d): cannot continue to read the key buffer.", fNbytes, fKeylen);
1265 MakeZombie();
1266 return;
1267 }
1268
1269 if(CheckKeyObjLenOverflow("ReadKeyBuffer", fKeylen, fObjlen)){
1270 fKeylen = 0;
1271 fObjlen = 0;
1272 MakeZombie();
1273 return;
1274 }
1275
1276 frombuf(buffer, &fCycle);
1277 if (fVersion > 1000) {
1278 frombuf(buffer, &fSeekKey);
1279
1280 // We currently store in the 16 highest bit of fSeekPdir the value of
1281 // fPidOffset. This offset is used when a key (or basket) is transferred from one
1282 // file to the other. In this case the TRef and TObject might have stored a
1283 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1284 // file, the fPidOffset is to be added to those values to correctly find the
1285 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1286 // and need to be zero for new key/basket.
1287 Long64_t pdir;
1288 frombuf(buffer, &pdir);
1289 fPidOffset = pdir >> kPidOffsetShift;
1290 fSeekPdir = pdir & kPidOffsetMask;
1291 } else {
1292 UInt_t seekkey,seekdir;
1293 frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey;
1294 frombuf(buffer, &seekdir); fSeekPdir= (Long64_t)seekdir;
1295 }
1296 fClassName.ReadBuffer(buffer);
1297 //the following test required for forward and backward compatibility
1298 if (fClassName == "TDirectory") {
1299 fClassName = "TDirectoryFile";
1301 }
1302
1303 fName.ReadBuffer(buffer);
1304 fTitle.ReadBuffer(buffer);
1305}
1306
1307////////////////////////////////////////////////////////////////////////////////
1308/// Decode input buffer.
1309/// \return true if decoding was successful.
1310
1311bool TKey::ReadKeyBuffer(char *&buffer, std::size_t bufsize)
1312{
1313 // NOTE: this is not a lambda because we want [[nodiscard]].
1314 struct {
1315 TKey *fOuter;
1316 std::size_t fRemainingBufSize;
1317 [[nodiscard]] bool operator()(std::size_t additionalBytesNeeded) {
1318 if (R__unlikely(additionalBytesNeeded > fRemainingBufSize)) {
1319 fOuter->Error("ReadKeyBuffer", "The given buffer is too small to fit this TKey.");
1320 fOuter->MakeZombie();
1321 return false;
1322 }
1323 fRemainingBufSize -= additionalBytesNeeded;
1324 return true;
1325 }
1326 } ConsumeBufCapacity{this, bufsize};
1327
1328 // Min size of the buffer for reading the common key header data
1329 constexpr std::size_t kMinBufSize =
1330 sizeof(fNbytes) + sizeof(Version_t) + sizeof(fObjlen) + sizeof(fKeylen) + sizeof(fCycle);
1331 if (!ConsumeBufCapacity(kMinBufSize))
1332 return false;
1333
1334 frombuf(buffer, &fNbytes);
1335 if (fNbytes < 0) {
1336 Error("ReadKeyBuffer", "The value of fNbytes is negative (%d): cannot continue to read the key buffer.", fNbytes);
1337 MakeZombie();
1338 fNbytes = 0;
1339 return false;
1340 }
1341 Version_t version;
1342 frombuf(buffer,&version);
1343 fVersion = (Int_t)version;
1344 frombuf(buffer, &fObjlen);
1345 if (fObjlen < 0) {
1346 Error("ReadKeyBuffer", "The value of fObjlen is negative (%d): cannot continue to read the key buffer.", fObjlen);
1347 MakeZombie();
1348 fObjlen = 0;
1349 return false;
1350 }
1351 fDatime.ReadBuffer(buffer);
1352 frombuf(buffer, &fKeylen);
1353 if (fKeylen < 0) {
1354 Error("ReadKeyBuffer", "The value of fKeylen is negative (%d): cannot continue to read the key buffer.", fKeylen);
1355 MakeZombie();
1356 fKeylen = 0;
1357 return false;
1358 }
1359
1360 if (fNbytes < fKeylen) {
1361 Error("ReadKeyBuffer", "fNbytes (%d) < fKeylen (%d): cannot continue to read the key buffer.", fNbytes, fKeylen);
1362 MakeZombie();
1363 return false;
1364 }
1365
1366 constexpr auto maxInt_t = std::numeric_limits<Int_t>::max();
1367 if (fKeylen > (maxInt_t - fObjlen)) {
1368 Error("ReadKeyBuffer", "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.", fObjlen, fKeylen, maxInt_t);
1369 MakeZombie();
1370 return false;
1371 }
1372
1373 frombuf(buffer, &fCycle);
1374 // The initial bufsize check guarantees that we could read up to here.
1375 // From now on we need to be careful.
1376
1377 if (fVersion > 1000) {
1378 if (!ConsumeBufCapacity(sizeof(fSeekKey) + sizeof(Long64_t)))
1379 return false;
1380
1381 frombuf(buffer, &fSeekKey);
1382
1383 // We currently store in the 16 highest bit of fSeekPdir the value of
1384 // fPidOffset. This offset is used when a key (or basket) is transferred from one
1385 // file to the other. In this case the TRef and TObject might have stored a
1386 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1387 // file, the fPidOffset is to be added to those values to correctly find the
1388 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1389 // and need to be zero for new key/basket.
1390 Long64_t pdir;
1391 frombuf(buffer, &pdir);
1392 fPidOffset = pdir >> kPidOffsetShift;
1393 fSeekPdir = pdir & kPidOffsetMask;
1394 } else {
1395 if (!ConsumeBufCapacity(2 * sizeof(UInt_t)))
1396 return false;
1397
1398 UInt_t seekkey,seekdir;
1399 frombuf(buffer, &seekkey);
1400 fSeekKey = (Long64_t)seekkey;
1401 frombuf(buffer, &seekdir);
1402 fSeekPdir = (Long64_t)seekdir;
1403 }
1404
1405 auto nRead = fClassName.ReadBuffer(buffer, ConsumeBufCapacity.fRemainingBufSize);
1406 if (!nRead) {
1407 MakeZombie();
1408 return false;
1409 }
1410 ConsumeBufCapacity.fRemainingBufSize -= nRead;
1411
1412 //the following test required for forward and backward compatibility
1413 if (fClassName == "TDirectory") {
1414 fClassName = "TDirectoryFile";
1416 }
1417
1418 nRead = fName.ReadBuffer(buffer, ConsumeBufCapacity.fRemainingBufSize);
1419 if (!nRead) {
1420 MakeZombie();
1421 return false;
1422 }
1423 ConsumeBufCapacity.fRemainingBufSize -= nRead;
1424
1425 nRead = fTitle.ReadBuffer(buffer, ConsumeBufCapacity.fRemainingBufSize);
1426 if (!nRead) {
1427 MakeZombie();
1428 return false;
1429 }
1430 return true;
1431}
1432
1433////////////////////////////////////////////////////////////////////////////////
1434/// Read the key structure from the file
1435
1437{
1438 TFile* f = GetFile();
1439 if (f==0) return kFALSE;
1440
1441 Int_t nsize = fNbytes;
1442 f->Seek(fSeekKey);
1443 if( f->ReadBuffer(fBuffer,nsize) )
1444 {
1445 Error("ReadFile", "Failed to read data.");
1446 return kFALSE;
1447 }
1448 if (gDebug) {
1449 std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
1450 }
1451 return kTRUE;
1452}
1453
1454////////////////////////////////////////////////////////////////////////////////
1455/// Set parent in key buffer.
1456
1457void TKey::SetParent(const TObject *parent)
1458{
1459 if (fBufferRef) fBufferRef->SetParent((TObject*)parent);
1460}
1461
1462////////////////////////////////////////////////////////////////////////////////
1463/// Reset the key as it had not been 'filled' yet.
1464
1466{
1467 fPidOffset = 0;
1468 fNbytes = 0;
1469 fBuffer = 0;
1470 fObjlen = 0;
1471 fCycle = 0;
1472 fSeekPdir = 0;
1473 fSeekKey = 0;
1474 fLeft = 0;
1475 fDatime = (UInt_t)0;
1476
1477 // fBufferRef and fKeylen intentionally not reset/changed
1478
1480}
1481
1482////////////////////////////////////////////////////////////////////////////////
1483/// Return the size in bytes of the key header structure.
1484///
1485/// An explanation about the nbytes (Int_t nbytes) variable used in the
1486/// function. The size of fSeekKey and fSeekPdir is 8 instead of 4 if version is
1487/// greater than 1000.
1488/// | Component | Sizeof |
1489/// |-------------------|------------|
1490/// | fNbytes | 4 |
1491/// | sizeof(Version_t) | 2 |
1492/// | fObjlen | 4 |
1493/// | fDatime | 4 |
1494/// | fKeylen | 2 |
1495/// | fCycle | 2 |
1496/// | fSeekKey | 4 or 8 |
1497/// | fSeekPdir | 4 or 8 |
1498/// | **FIXED TOTAL** | 26 or 34 |
1499/// | fClassName | 1+ bytes |
1500/// | fName | 1+ bytes |
1501/// | fTitle | 1+ bytes |
1502/// | **TOTAL** | 29+ or 37+ |
1503
1505{
1506 Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8;
1507 nbytes += fDatime.Sizeof();
1509 nbytes += 11; // strlen("TDirectory")+1
1510 } else {
1511 nbytes += fClassName.Sizeof();
1512 }
1513 nbytes += fName.Sizeof();
1514 nbytes += fTitle.Sizeof();
1515 return nbytes;
1516}
1517
1518////////////////////////////////////////////////////////////////////////////////
1519/// Stream a class object.
1520
1522{
1523 Version_t version;
1524 if (b.IsReading()) {
1525 b >> fNbytes;
1526 b >> version; fVersion = (Int_t)version;
1527 b >> fObjlen;
1529 b >> fKeylen;
1530 b >> fCycle;
1531 if (fVersion > 1000) {
1532 b >> fSeekKey;
1533
1534 // We currently store in the 16 highest bit of fSeekPdir the value of
1535 // fPidOffset. This offset is used when a key (or basket) is transferred from one
1536 // file to the other. In this case the TRef and TObject might have stored a
1537 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1538 // file, the fPidOffset is to be added to those values to correctly find the
1539 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1540 // and need to be zero for new key/basket.
1541 Long64_t pdir;
1542 b >> pdir;
1543 fPidOffset = pdir >> kPidOffsetShift;
1544 fSeekPdir = pdir & kPidOffsetMask;
1545 } else {
1546 UInt_t seekkey, seekdir;
1547 b >> seekkey; fSeekKey = (Long64_t)seekkey;
1548 b >> seekdir; fSeekPdir= (Long64_t)seekdir;
1549 }
1551 //the following test required for forward and backward compatibility
1552 if (fClassName == "TDirectory") {
1553 fClassName = "TDirectoryFile";
1555 }
1556 fName.Streamer(b);
1557 fTitle.Streamer(b);
1558 if (fKeylen < 0) {
1559 Error("Streamer","The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero",fKeylen);
1560 MakeZombie();
1561 fKeylen = 0;
1562 }
1563 if (fObjlen < 0) {
1564 Error("Streamer","The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero",fObjlen);
1565 MakeZombie();
1566 fObjlen = 0;
1567 }
1568 if (fNbytes < 0) {
1569 Error("Streamer","The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero",fNbytes);
1570 MakeZombie();
1571 fNbytes = 0;
1572 }
1573 if (CheckKeyObjLenOverflow("Streamer", fKeylen, fObjlen)) {
1574 MakeZombie();
1575 return;
1576 }
1577
1578 } else {
1579 b << fNbytes;
1580 version = (Version_t)fVersion;
1581 b << version;
1582 b << fObjlen;
1583 if (fDatime.Get() == 0) fDatime.Set();
1585 TDatime((UInt_t) 1).Streamer(b);
1586 else
1588 b << fKeylen;
1589 b << fCycle;
1590 if (fVersion > 1000) {
1591 b << fSeekKey;
1592
1593 // We currently store in the 16 highest bit of fSeekPdir the value of
1594 // fPidOffset. This offset is used when a key (or basket) is transferred from one
1595 // file to the other. In this case the TRef and TObject might have stored a
1596 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1597 // file, the fPidOffset is to be added to those values to correctly find the
1598 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1599 // and need to be zero for new key/basket.
1601 b << pdir;
1602 } else {
1603 b << (Int_t)fSeekKey;
1604 b << (Int_t)fSeekPdir;
1605 }
1607 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
1608 b.WriteTString(gTDirectoryString);
1609 } else {
1611 }
1612 fName.Streamer(b);
1613 fTitle.Streamer(b);
1614 }
1615}
1616
1617////////////////////////////////////////////////////////////////////////////////
1618/// Write the encoded object supported by this key.
1619/// The function returns the number of bytes committed to the file.
1620/// If a write error occurs, the number of bytes returned is -1.
1621
1623{
1624 if (!f) f = GetFile();
1625 if (!f) return -1;
1626
1627 Int_t nsize = fNbytes;
1628 char *buffer = fBuffer;
1629 if (cycle) {
1630 fCycle = cycle;
1631 FillBuffer(buffer);
1632 buffer = fBuffer;
1633 }
1634
1635 if (fLeft > 0) nsize += sizeof(Int_t);
1636 f->Seek(fSeekKey);
1637 Bool_t result = f->WriteBuffer(buffer,nsize);
1638 //f->Flush(); Flushing takes too much time.
1639 // Let user flush the file when they want.
1640 if (gDebug) {
1641 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1642 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1643 }
1644
1645 DeleteBuffer();
1646 return result==kTRUE ? -1 : nsize;
1647}
1648
1649////////////////////////////////////////////////////////////////////////////////
1650/// Write the encoded object supported by this key.
1651/// The function returns the number of bytes committed to the file.
1652/// If a write error occurs, the number of bytes returned is -1.
1653
1655{
1656 if (!f) f = GetFile();
1657 if (!f) return -1;
1658
1659 Int_t nsize = fNbytes;
1660 char *buffer = fBuffer;
1661
1662 if (fLeft > 0) nsize += sizeof(Int_t);
1663 f->Seek(fSeekKey);
1664 Bool_t result = f->WriteBuffer(buffer,nsize);
1665 //f->Flush(); Flushing takes too much time.
1666 // Let user flush the file when they want.
1667 if (gDebug) {
1668 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1669 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1670 }
1671
1672 return result==kTRUE ? -1 : nsize;
1673}
1674
1675////////////////////////////////////////////////////////////////////////////////
1676/// Title can keep 32x32 xpm thumbnail/icon of the parent object.
1677
1678const char *TKey::GetIconName() const
1679{
1680 return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0);
1681}
1682
1683////////////////////////////////////////////////////////////////////////////////
1684/// Returns title (title can contain 32x32 xpm thumbnail/icon).
1685
1686const char *TKey::GetTitle() const
1687{
1688 if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) { // title contains xpm thumbnail
1689 static TString ret;
1690 int start = fTitle.Index("/*") + 3;
1691 int stop = fTitle.Index("*/") - 1;
1692 ret = fTitle(start, stop - start);
1693 return ret.Data();
1694 }
1695 return fTitle.Data();
1696}
void frombuf(char *&buf, Bool_t *x)
Definition Bytes.h:270
void tobuf(char *&buf, Bool_t x)
Definition Bytes.h:55
#define R__unlikely(expr)
Definition RConfig.hxx:568
#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:55
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char)
Definition RtypesCore.h:53
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:84
unsigned long long ULong64_t
Portable unsigned long integer 8 bytes.
Definition RtypesCore.h:85
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
#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:139
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
#define gFile
Definition TFile.h:439
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:142
const ULong64_t kPidOffsetMask
Definition TKey.cxx:74
static const TString gTDirectoryString("TDirectory")
const Int_t kTitleMax
Definition TKey.cxx:71
std::atomic< UInt_t > keyAbsNumber
Definition TKey.cxx:81
const UChar_t kPidOffsetShift
Definition TKey.cxx:78
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:792
#define gROOT
Definition TROOT.h:417
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
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
Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr) override
Read class version from I/O buffer.
void MapObject(const TObject *obj, UInt_t offset=1) override
Add object to the fMap container.
void SetPidOffset(UShort_t offset) override
This offset is used when a key (or basket) is transferred from one file to the other.
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:627
void Browse(TBrowser *b) override
This method is called by a browser to get the class information.
Definition TClass.cxx:2022
EState GetState() const
Definition TClass.h:504
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5111
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5533
void * DynamicCast(const TClass *base, void *obj, Bool_t up=kTRUE)
Cast obj of this class type up to baseclass cl if up is true.
Definition TClass.cxx:5036
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7715
@ kDummyNew
Definition TClass.h:110
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition TClass.cxx:1939
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:6106
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4995
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2817
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition TClass.cxx:7613
@ kEmulated
Definition TClass.h:128
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2619
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:2999
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:236
void FillBuffer(char *&buffer)
Encode Date/Time into buffer, used by I/O system.
Definition TDatime.cxx:225
Int_t Sizeof() const
Definition TDatime.h:81
virtual void Streamer(TBuffer &)
Stream a object of type TDatime.
Definition TDatime.cxx:412
void Set()
Set Date/Time to current time as reported by the system.
Definition TDatime.cxx:285
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition TDatime.cxx:274
A ROOT file is structured in Directories (like a file system).
Long64_t GetSeekDir() const override
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 file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
Int_t GetCompressionLevel() const
Definition TFile.h:483
virtual Long64_t GetEND() const
Definition TFile.h:319
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition TFile.cxx:1510
@ kStartBigFile
Definition TFile.h:278
Int_t GetCompressionAlgorithm() const
Definition TFile.h:477
@ kReproducible
Definition TFile.h:271
Service class for TFile.
Definition TFree.h:27
Long64_t GetLast() const
Definition TFree.h:41
void SetFirst(Long64_t first)
Definition TFree.h:44
void SetLast(Long64_t last)
Definition TFree.h:45
Long64_t GetFirst() const
Definition TFree.h:40
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:1686
static constexpr Version_t Class_Version()
Definition TKey.h:119
void Delete(Option_t *option="") override
Delete an object from the file.
Definition TKey.cxx:592
@ 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:1504
TKey()
TKey default constructor.
Definition TKey.cxx:99
~TKey() override
TKey default destructor.
Definition TKey.cxx:579
TFile * GetFile() const
Returns file to which key belong.
Definition TKey.cxx:639
virtual void Keep()
Set the "KEEP" status.
Definition TKey.cxx:739
const char * GetIconName() const override
Title can keep 32x32 xpm thumbnail/icon of the parent object.
Definition TKey.cxx:1678
Int_t Read(const char *name) override
Read contents of object with specified name from the current directory.
Definition TKey.h:56
Int_t UnzipBuffer(char *targetBuffer, const char *compressedBuffer) const
Core of uncompressing the key payload.
Definition TKey.cxx:411
TDatime fDatime
Date/Time of insertion in file.
Definition TKey.h:44
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition TKey.h:52
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:53
virtual void IncrementPidOffset(UShort_t offset)
Increment fPidOffset by 'offset'.
Definition TKey.cxx:704
Short_t GetKeep() const
Returns the "KEEP" status.
Definition TKey.cxx:647
Int_t fVersion
Key version identifier.
Definition TKey.h:41
Bool_t IsFolder() const override
Check if object referenced by the key is a folder.
Definition TKey.cxx:718
Int_t fLeft
Number of bytes left in current segment.
Definition TKey.h:50
virtual const char * GetClassName() const
Definition TKey.h:77
Short_t fKeylen
Number of bytes for the key itself.
Definition TKey.h:45
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition TKey.cxx:1436
void Browse(TBrowser *b) override
Read object from disk and call its Browse() method.
Definition TKey.cxx:481
virtual Int_t WriteFileKeepBuffer(TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1654
Long64_t fSeekKey
Location of object on file.
Definition TKey.h:47
void Build(TDirectory *motherDir, const char *classname, Long64_t filepos)
Method used in all TKey constructor to initialize basic data fields.
Definition TKey.cxx:443
char * fBuffer
Object buffer.
Definition TKey.h:51
Long64_t fSeekPdir
Location of parent directory on file.
Definition TKey.h:48
virtual void SetParent(const TObject *parent)
Set parent in key buffer.
Definition TKey.cxx:1457
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition TKey.cxx:1051
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1235
Int_t fNbytes
Number of bytes for the whole key on file (key header and data)
Definition TKey.h:42
Int_t fObjlen
Length of uncompressed object in bytes.
Definition TKey.h:43
void Reset()
Reset the key as it had not been 'filled' yet.
Definition TKey.cxx:1465
Short_t fCycle
Cycle number.
Definition TKey.h:46
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition TKey.cxx:933
virtual void ls(Bool_t current) const
List Key contents.
Definition TKey.cxx:748
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:631
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:812
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
Definition TKey.cxx:513
virtual void DeleteBuffer()
Delete key buffer(s).
Definition TKey.cxx:613
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1622
virtual void ReadBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1223
TDirectory * fMotherDir
!pointer to mother directory
Definition TKey.h:54
TString fClassName
Object Class name.
Definition TKey.h:49
void Print(Option_t *option="") const override
Print key contents.
Definition TKey.cxx:768
void FillBuffer(char *&buffer) override
Encode key header into output buffer.
Definition TKey.cxx:655
void Streamer(TBuffer &) override
Stream a class object.
Definition TKey.cxx:1521
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
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:42
virtual Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition TObject.cxx:578
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:995
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void UseCurrentStyle()
Set current style settings in this object This function is called when either TCanvas::UseCurrentStyl...
Definition TObject.cxx:907
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
static TClass * Class()
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:267
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1124
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:897
virtual TClass * IsA() const
Definition TObject.h:248
void MakeZombie()
Definition TObject.h:55
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1070
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:3067
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
const char * Data() const
Definition TString.h:385
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:633
Bool_t IsNull() const
Definition TString.h:423
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:1493
virtual Int_t Sizeof() const
Returns size string will occupy on I/O buffer.
Definition TString.cxx:1482
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:661
TF1 * f1
Definition legend1.C:11
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition Rtypes.h:119
EValues
Note: this is only temporarily a struct and will become a enum class hence the name convention used.
Definition Compression.h:88