00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "Riostream.h"
00050 #include "TROOT.h"
00051 #include "TClass.h"
00052 #include "TDirectoryFile.h"
00053 #include "TFile.h"
00054 #include "TKey.h"
00055 #include "TBufferFile.h"
00056 #include "TFree.h"
00057 #include "TBrowser.h"
00058 #include "Bytes.h"
00059 #include "TInterpreter.h"
00060 #include "TError.h"
00061 #include "TVirtualStreamerInfo.h"
00062 #include "TSchemaRuleSet.h"
00063
00064 extern "C" void R__zip (Int_t cxlevel, Int_t *nin, char *bufin, Int_t *lout, char *bufout, Int_t *nout);
00065 extern "C" void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout);
00066 extern "C" int R__unzip_header(Int_t *nin, UChar_t *bufin, Int_t *lout);
00067 const Int_t kMAXBUF = 0xffffff;
00068 const Int_t kTitleMax = 32000;
00069 #if 0
00070 const Int_t kMAXFILEBUFFER = 262144;
00071 #endif
00072
00073 #if !defined(_MSC_VER) || (_MSC_VER>1300)
00074 const ULong64_t kPidOffsetMask = 0xffffffffffffULL;
00075 #else
00076 const ULong64_t kPidOffsetMask = 0xffffffffffffUL;
00077 #endif
00078 const UChar_t kPidOffsetShift = 48;
00079
00080 UInt_t keyAbsNumber = 0;
00081
00082 ClassImp(TKey)
00083
00084
00085 TKey::TKey() : TNamed(), fDatime((UInt_t)0)
00086 {
00087
00088
00089 Build(0, "", 0);
00090
00091 fKeylen = Sizeof();
00092
00093 keyAbsNumber++; SetUniqueID(keyAbsNumber);
00094 }
00095
00096
00097 TKey::TKey(TDirectory* motherDir) : TNamed(), fDatime((UInt_t)0)
00098 {
00099
00100
00101 Build(motherDir, "", 0);
00102
00103 fKeylen = Sizeof();
00104
00105 keyAbsNumber++; SetUniqueID(keyAbsNumber);
00106 }
00107
00108
00109 TKey::TKey(Long64_t pointer, Int_t nbytes, TDirectory* motherDir) : TNamed()
00110 {
00111
00112
00113
00114
00115 Build(motherDir, "", pointer);
00116
00117 fSeekKey = pointer;
00118 fNbytes = nbytes;
00119 fBuffer = new char[nbytes];
00120 keyAbsNumber++; SetUniqueID(keyAbsNumber);
00121 }
00122
00123
00124 TKey::TKey(const char *name, const char *title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
00125 : TNamed(name,title)
00126 {
00127
00128
00129
00130
00131
00132 Build(motherDir, cl->GetName(), -1);
00133
00134 fKeylen = Sizeof();
00135 fObjlen = nbytes;
00136 Create(nbytes);
00137 }
00138
00139
00140 TKey::TKey(const TString &name, const TString &title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
00141 : TNamed(name,title)
00142 {
00143
00144
00145
00146
00147
00148 Build(motherDir, cl->GetName(), -1);
00149
00150 fKeylen = Sizeof();
00151 fObjlen = nbytes;
00152 Create(nbytes);
00153 }
00154
00155
00156 TKey::TKey(const TObject *obj, const char *name, Int_t bufsize, TDirectory* motherDir)
00157 : TNamed(name, obj->GetTitle())
00158 {
00159
00160
00161
00162
00163
00164 R__ASSERT(obj);
00165
00166 if (!obj->IsA()->HasDefaultConstructor()) {
00167 Warning("TKey", "since %s has no public constructor\n"
00168 "\twhich can be called without argument, objects of this class\n"
00169 "\tcan not be read with the current library. You will need to\n"
00170 "\tadd a default constructor before attempting to read it.",
00171 obj->ClassName());
00172 }
00173
00174 Build(motherDir, obj->ClassName(), -1);
00175
00176 Int_t lbuf, nout, noutot, bufmax, nzip;
00177 fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize);
00178 fBufferRef->SetParent(GetFile());
00179 fCycle = fMotherDir->AppendKey(this);
00180
00181 Streamer(*fBufferRef);
00182 fKeylen = fBufferRef->Length();
00183 fBufferRef->MapObject(obj);
00184 ((TObject*)obj)->Streamer(*fBufferRef);
00185 lbuf = fBufferRef->Length();
00186 fObjlen = lbuf - fKeylen;
00187
00188 Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0;
00189 if (cxlevel && fObjlen > 256) {
00190 if (cxlevel == 2) cxlevel--;
00191 Int_t nbuffers = fObjlen/kMAXBUF;
00192 Int_t buflen = TMath::Max(512,fKeylen + fObjlen + 9*nbuffers + 28);
00193 fBuffer = new char[buflen];
00194 char *objbuf = fBufferRef->Buffer() + fKeylen;
00195 char *bufcur = &fBuffer[fKeylen];
00196 noutot = 0;
00197 nzip = 0;
00198 for (Int_t i=0;i<=nbuffers;i++) {
00199 if (i == nbuffers) bufmax = fObjlen -nzip;
00200 else bufmax = kMAXBUF;
00201 R__zip(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout);
00202 if (nout == 0 || nout >= fObjlen) {
00203 fBuffer = fBufferRef->Buffer();
00204 Create(fObjlen);
00205 fBufferRef->SetBufferOffset(0);
00206 Streamer(*fBufferRef);
00207 return;
00208 }
00209 bufcur += nout;
00210 noutot += nout;
00211 objbuf += kMAXBUF;
00212 nzip += kMAXBUF;
00213 }
00214 Create(noutot);
00215 fBufferRef->SetBufferOffset(0);
00216 Streamer(*fBufferRef);
00217 memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
00218 delete fBufferRef; fBufferRef = 0;
00219 } else {
00220 fBuffer = fBufferRef->Buffer();
00221 Create(fObjlen);
00222 fBufferRef->SetBufferOffset(0);
00223 Streamer(*fBufferRef);
00224 }
00225 }
00226
00227
00228 TKey::TKey(const void *obj, const TClass *cl, const char *name, Int_t bufsize, TDirectory* motherDir)
00229 : TNamed(name, "object title")
00230 {
00231
00232
00233
00234
00235
00236
00237 R__ASSERT(obj && cl);
00238
00239 if (!cl->HasDefaultConstructor()) {
00240 Warning("TKey", "since %s has no public constructor\n"
00241 "\twhich can be called without argument, objects of this class\n"
00242 "\tcan not be read with the current library. You will need to\n"
00243 "\tadd a default constructor before attempting to read it.",
00244 cl->GetName());
00245 }
00246
00247 TClass *clActual = cl->GetActualClass(obj);
00248 const void* actualStart;
00249 if (clActual) {
00250 const char *temp = (const char*) obj;
00251
00252 Int_t offset = (cl != clActual) ?
00253 clActual->GetBaseClassOffset(cl) : 0;
00254 temp -= offset;
00255 actualStart = temp;
00256 } else {
00257
00258
00259 clActual = const_cast<TClass*>(cl);
00260 actualStart = obj;
00261 }
00262
00263 Build(motherDir, clActual->GetName(), -1);
00264
00265 fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize);
00266 fBufferRef->SetParent(GetFile());
00267 fCycle = fMotherDir->AppendKey(this);
00268
00269 Streamer(*fBufferRef);
00270 fKeylen = fBufferRef->Length();
00271
00272 Int_t lbuf, nout, noutot, bufmax, nzip;
00273
00274 fBufferRef->MapObject(actualStart,clActual);
00275 clActual->Streamer((void*)actualStart, *fBufferRef);
00276 lbuf = fBufferRef->Length();
00277 fObjlen = lbuf - fKeylen;
00278
00279 Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0;
00280 if (cxlevel && fObjlen > 256) {
00281 if (cxlevel == 2) cxlevel--;
00282 Int_t nbuffers = fObjlen/kMAXBUF;
00283 Int_t buflen = TMath::Max(512,fKeylen + fObjlen + 9*nbuffers + 28);
00284 fBuffer = new char[buflen];
00285 char *objbuf = fBufferRef->Buffer() + fKeylen;
00286 char *bufcur = &fBuffer[fKeylen];
00287 noutot = 0;
00288 nzip = 0;
00289 for (Int_t i=0;i<=nbuffers;i++) {
00290 if (i == nbuffers) bufmax = fObjlen -nzip;
00291 else bufmax = kMAXBUF;
00292 R__zip(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout);
00293 if (nout == 0 || nout >= fObjlen) {
00294 fBuffer = fBufferRef->Buffer();
00295 Create(fObjlen);
00296 fBufferRef->SetBufferOffset(0);
00297 Streamer(*fBufferRef);
00298 return;
00299 }
00300 bufcur += nout;
00301 noutot += nout;
00302 objbuf += kMAXBUF;
00303 nzip += kMAXBUF;
00304 }
00305 Create(noutot);
00306 fBufferRef->SetBufferOffset(0);
00307 Streamer(*fBufferRef);
00308 memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
00309 delete fBufferRef; fBufferRef = 0;
00310 } else {
00311 fBuffer = fBufferRef->Buffer();
00312 Create(fObjlen);
00313 fBufferRef->SetBufferOffset(0);
00314 Streamer(*fBufferRef);
00315 }
00316 }
00317
00318
00319 void TKey::Build(TDirectory* motherDir, const char* classname, Long64_t filepos)
00320 {
00321
00322
00323
00324
00325 fMotherDir = motherDir;
00326
00327 fPidOffset = 0;
00328 fNbytes = 0;
00329 fBuffer = 0;
00330 fKeylen = 0;
00331 fObjlen = 0;
00332 fBufferRef = 0;
00333 fCycle = 0;
00334 fSeekPdir = 0;
00335 fSeekKey = 0;
00336 fLeft = 0;
00337
00338 fClassName = classname;
00339
00340 if (fClassName == "TDirectoryFile") fClassName = "TDirectory";
00341
00342 fVersion = TKey::Class_Version();
00343
00344 if ((filepos==-1) && GetFile()) filepos = GetFile()->GetEND();
00345 if (filepos > TFile::kStartBigFile) fVersion += 1000;
00346
00347 if (fTitle.Length() > kTitleMax) fTitle.Resize(kTitleMax);
00348 }
00349
00350
00351 void TKey::Browse(TBrowser *b)
00352 {
00353
00354
00355
00356
00357
00358
00359 if (fMotherDir==0) return;
00360
00361 TClass *objcl = TClass::GetClass(GetClassName());
00362
00363 void* obj = fMotherDir->GetList()->FindObject(GetName());
00364 if (obj && objcl->InheritsFrom(TObject::Class())) {
00365 TObject *tobj = (TObject*)obj;
00366 if (!tobj->IsFolder()) {
00367 if (tobj->InheritsFrom(TCollection::Class()))
00368 tobj->Delete();
00369 delete tobj;
00370 obj = 0;
00371 }
00372 }
00373
00374 if (!obj)
00375 obj = ReadObj();
00376
00377 if (b && obj) {
00378 objcl->Browse(obj,b);
00379 b->SetRefreshFlag(kTRUE);
00380 }
00381 }
00382
00383
00384 void TKey::Create(Int_t nbytes, TFile* externFile)
00385 {
00386
00387
00388
00389
00390 keyAbsNumber++; SetUniqueID(keyAbsNumber);
00391
00392 TFile *f = externFile;
00393 if (!f) f = GetFile();
00394 if (!f) {
00395 Error("Create","Cannot create key without file");
00396 return;
00397 }
00398
00399 Int_t nsize = nbytes + fKeylen;
00400 TList *lfree = f->GetListOfFree();
00401 TFree *f1 = (TFree*)lfree->First();
00402
00403
00404 TFree *bestfree = f1->GetBestFree(lfree,nsize);
00405 if (bestfree == 0) {
00406 Error("Create","Cannot allocate %d bytes for ID = %s Title = %s",
00407 nsize,GetName(),GetTitle());
00408 return;
00409 }
00410 fDatime.Set();
00411 fSeekKey = bestfree->GetFirst();
00412
00413 if (fSeekKey >= f->GetEND()) {
00414 f->SetEND(fSeekKey+nsize);
00415 bestfree->SetFirst(fSeekKey+nsize);
00416 fLeft = -1;
00417 if (!fBuffer) fBuffer = new char[nsize];
00418 } else {
00419 fLeft = Int_t(bestfree->GetLast() - fSeekKey - nsize + 1);
00420 }
00421
00422 fNbytes = nsize;
00423 if (fLeft == 0) {
00424 if (!fBuffer) {
00425 fBuffer = new char[nsize];
00426 }
00427 lfree->Remove(bestfree);
00428 delete bestfree;
00429 }
00430
00431 if (fLeft > 0) {
00432 if (!fBuffer) {
00433 fBuffer = new char[nsize+sizeof(Int_t)];
00434 }
00435 char *buffer = fBuffer+nsize;
00436 Int_t nbytesleft = -fLeft;
00437 tobuf(buffer, nbytesleft);
00438 bestfree->SetFirst(fSeekKey+nsize);
00439 }
00440
00441 fSeekPdir = externFile ? externFile->GetSeekDir() : fMotherDir->GetSeekDir();
00442 }
00443
00444
00445 TKey::~TKey()
00446 {
00447
00448
00449
00450
00451
00452 DeleteBuffer();
00453 }
00454
00455
00456 void TKey::Delete(Option_t *option)
00457 {
00458
00459
00460
00461
00462 if (option && option[0] == 'v') printf("Deleting key: %s at address %lld, nbytes = %d\n",GetName(),fSeekKey,fNbytes);
00463 Long64_t first = fSeekKey;
00464 Long64_t last = fSeekKey + fNbytes -1;
00465 if (GetFile()) GetFile()->MakeFree(first, last);
00466 fMotherDir->GetListOfKeys()->Remove(this);
00467 }
00468
00469
00470 void TKey::DeleteBuffer()
00471 {
00472
00473
00474 if (fBufferRef) {
00475 delete fBufferRef;
00476 fBufferRef = 0;
00477 } else {
00478
00479
00480 if (fBuffer) {
00481 delete [] fBuffer;
00482 }
00483 }
00484 fBuffer = 0;
00485 }
00486
00487
00488 Short_t TKey::GetCycle() const
00489 {
00490
00491
00492 return ((fCycle >0) ? fCycle : -fCycle);
00493 }
00494
00495
00496 TFile *TKey::GetFile() const
00497 {
00498
00499
00500 return fMotherDir!=0 ? fMotherDir->GetFile() : gFile;
00501 }
00502
00503
00504 Short_t TKey::GetKeep() const
00505 {
00506
00507
00508 return ((fCycle >0) ? 0 : 1);
00509 }
00510
00511
00512 void TKey::FillBuffer(char *&buffer)
00513 {
00514
00515
00516 tobuf(buffer, fNbytes);
00517 Version_t version = fVersion;
00518 tobuf(buffer, version);
00519
00520 tobuf(buffer, fObjlen);
00521 fDatime.FillBuffer(buffer);
00522 tobuf(buffer, fKeylen);
00523 tobuf(buffer, fCycle);
00524 if (fVersion > 1000) {
00525 tobuf(buffer, fSeekKey);
00526
00527
00528
00529
00530
00531
00532
00533
00534 Long64_t pdir = (((Long64_t)fPidOffset)<<kPidOffsetShift) | (kPidOffsetMask & fSeekPdir);
00535 tobuf(buffer, pdir);
00536 } else {
00537 tobuf(buffer, (Int_t)fSeekKey);
00538 tobuf(buffer, (Int_t)fSeekPdir);
00539 }
00540 fClassName.FillBuffer(buffer);
00541 fName.FillBuffer(buffer);
00542 fTitle.FillBuffer(buffer);
00543 }
00544
00545
00546 ULong_t TKey::Hash() const
00547 {
00548
00549
00550 return TNamed::Hash();
00551 }
00552
00553
00554 void TKey::IncrementPidOffset(UShort_t offset)
00555 {
00556
00557
00558
00559
00560
00561
00562
00563
00564 fPidOffset += offset;
00565 if (fPidOffset) {
00566
00567
00568
00569 if (fVersion<1000) fVersion += 1000;
00570 }
00571 }
00572
00573
00574 Bool_t TKey::IsFolder() const
00575 {
00576
00577
00578 Bool_t ret = kFALSE;
00579
00580 TClass *classPtr = TClass::GetClass((const char *) fClassName);
00581 if (classPtr && classPtr->GetClassInfo() && classPtr->InheritsFrom(TObject::Class())) {
00582 TObject *obj = (TObject *) classPtr->New(TClass::kDummyNew);
00583 if (obj) {
00584 ret = obj->IsFolder();
00585 delete obj;
00586 }
00587 }
00588
00589 return ret;
00590 }
00591
00592
00593 void TKey::Keep()
00594 {
00595
00596
00597
00598 if (fCycle >0) fCycle = -fCycle;
00599 }
00600
00601
00602 void TKey::ls(Option_t *) const
00603 {
00604
00605
00606 TROOT::IndentLevel();
00607 cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<endl;
00608 }
00609
00610
00611 void TKey::Print(Option_t *) const
00612 {
00613
00614
00615 printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle());
00616 }
00617
00618
00619 TObject *TKey::ReadObj()
00620 {
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 TClass *cl = TClass::GetClass(fClassName.Data());
00650 if (!cl) {
00651 Error("ReadObj", "Unknown class %s", fClassName.Data());
00652 return 0;
00653 }
00654 if (!cl->InheritsFrom(TObject::Class())) {
00655
00656 return (TObject*)ReadObjectAny(0);
00657 }
00658
00659 fBufferRef = new TBufferFile(TBuffer::kRead, fObjlen+fKeylen);
00660 if (!fBufferRef) {
00661 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
00662 return 0;
00663 }
00664 if (GetFile()==0) return 0;
00665 fBufferRef->SetParent(GetFile());
00666 fBufferRef->SetPidOffset(fPidOffset);
00667
00668 if (fObjlen > fNbytes-fKeylen) {
00669 fBuffer = new char[fNbytes];
00670 ReadFile();
00671 memcpy(fBufferRef->Buffer(),fBuffer,fKeylen);
00672 } else {
00673 fBuffer = fBufferRef->Buffer();
00674 ReadFile();
00675 }
00676
00677
00678 fBufferRef->SetBufferOffset(sizeof(fNbytes));
00679 Version_t kvers = fBufferRef->ReadVersion();
00680
00681 fBufferRef->SetBufferOffset(fKeylen);
00682 TObject *tobj = 0;
00683
00684
00685 char *pobj = (char*)cl->New();
00686 Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
00687 if (baseOffset==-1) {
00688
00689
00690
00691 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
00692 fClassName.Data());
00693 }
00694 tobj = (TObject*)(pobj+baseOffset);
00695 if (!pobj) {
00696 Error("ReadObj", "Cannot create new object of class %s", fClassName.Data());
00697 return 0;
00698 }
00699 if (kvers > 1)
00700 fBufferRef->MapObject(pobj,cl);
00701
00702 if (fObjlen > fNbytes-fKeylen) {
00703 char *objbuf = fBufferRef->Buffer() + fKeylen;
00704 UChar_t *bufcur = (UChar_t *)&fBuffer[fKeylen];
00705 Int_t nin, nout, nbuf;
00706 Int_t noutot = 0;
00707 while (1) {
00708 Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
00709 if (hc!=0) break;
00710 R__unzip(&nin, bufcur, &nbuf, objbuf, &nout);
00711 if (!nout) break;
00712 noutot += nout;
00713 if (noutot >= fObjlen) break;
00714 bufcur += nin;
00715 objbuf += nout;
00716 }
00717 if (nout) {
00718 tobj->Streamer(*fBufferRef);
00719 delete [] fBuffer;
00720 } else {
00721 delete [] fBuffer;
00722 delete pobj;
00723 pobj = 0;
00724 tobj = 0;
00725 goto CLEAR;
00726 }
00727 } else {
00728 tobj->Streamer(*fBufferRef);
00729 }
00730
00731 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
00732
00733 if (cl->InheritsFrom(TDirectoryFile::Class())) {
00734 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
00735 dir->SetName(GetName());
00736 dir->SetTitle(GetTitle());
00737 dir->SetMother(fMotherDir);
00738 fMotherDir->Append(dir);
00739 }
00740
00741
00742 {
00743 ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
00744 if (addfunc) {
00745 addfunc(pobj, fMotherDir);
00746 }
00747 }
00748
00749 CLEAR:
00750 delete fBufferRef;
00751 fBufferRef = 0;
00752 fBuffer = 0;
00753
00754 return tobj;
00755 }
00756
00757
00758 TObject *TKey::ReadObjWithBuffer(char *bufferRead)
00759 {
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 TClass *cl = TClass::GetClass(fClassName.Data());
00778 if (!cl) {
00779 Error("ReadObjWithBuffer", "Unknown class %s", fClassName.Data());
00780 return 0;
00781 }
00782 if (!cl->InheritsFrom(TObject::Class())) {
00783
00784 return (TObject*)ReadObjectAny(0);
00785 }
00786
00787 fBufferRef = new TBufferFile(TBuffer::kRead, fObjlen+fKeylen);
00788 if (!fBufferRef) {
00789 Error("ReadObjWithBuffer", "Cannot allocate buffer: fObjlen = %d", fObjlen);
00790 return 0;
00791 }
00792 if (GetFile()==0) return 0;
00793 fBufferRef->SetParent(GetFile());
00794 fBufferRef->SetPidOffset(fPidOffset);
00795
00796 if (fObjlen > fNbytes-fKeylen) {
00797 fBuffer = bufferRead;
00798 memcpy(fBufferRef->Buffer(),fBuffer,fKeylen);
00799 } else {
00800 fBuffer = fBufferRef->Buffer();
00801 ReadFile();
00802 }
00803
00804
00805 fBufferRef->SetBufferOffset(sizeof(fNbytes));
00806 Version_t kvers = fBufferRef->ReadVersion();
00807
00808 fBufferRef->SetBufferOffset(fKeylen);
00809 TObject *tobj = 0;
00810
00811
00812 char *pobj = (char*)cl->New();
00813 Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
00814 if (baseOffset==-1) {
00815
00816
00817
00818 Fatal("ReadObjWithBuffer","Incorrect detection of the inheritance from TObject for class %s.\n",
00819 fClassName.Data());
00820 }
00821 tobj = (TObject*)(pobj+baseOffset);
00822 if (!pobj) {
00823 Error("ReadObjWithBuffer", "Cannot create new object of class %s", fClassName.Data());
00824 return 0;
00825 }
00826 if (kvers > 1)
00827 fBufferRef->MapObject(pobj,cl);
00828
00829 if (fObjlen > fNbytes-fKeylen) {
00830 char *objbuf = fBufferRef->Buffer() + fKeylen;
00831 UChar_t *bufcur = (UChar_t *)&fBuffer[fKeylen];
00832 Int_t nin, nout, nbuf;
00833 Int_t noutot = 0;
00834 while (1) {
00835 Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
00836 if (hc!=0) break;
00837 R__unzip(&nin, bufcur, &nbuf, objbuf, &nout);
00838 if (!nout) break;
00839 noutot += nout;
00840 if (noutot >= fObjlen) break;
00841 bufcur += nin;
00842 objbuf += nout;
00843 }
00844 if (nout) {
00845 tobj->Streamer(*fBufferRef);
00846 } else {
00847 delete pobj;
00848 pobj = 0;
00849 tobj = 0;
00850 goto CLEAR;
00851 }
00852 } else {
00853 tobj->Streamer(*fBufferRef);
00854 }
00855
00856 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
00857
00858 if (cl->InheritsFrom(TDirectoryFile::Class())) {
00859 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
00860 dir->SetName(GetName());
00861 dir->SetTitle(GetTitle());
00862 dir->SetMother(fMotherDir);
00863 fMotherDir->Append(dir);
00864 }
00865
00866
00867 {
00868 ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
00869 if (addfunc) {
00870 addfunc(pobj, fMotherDir);
00871 }
00872 }
00873
00874 CLEAR:
00875 delete fBufferRef;
00876 fBufferRef = 0;
00877 fBuffer = 0;
00878
00879 return tobj;
00880 }
00881
00882
00883 void *TKey::ReadObjectAny(const TClass* expectedClass)
00884 {
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 fBufferRef = new TBufferFile(TBuffer::kRead, fObjlen+fKeylen);
00910 if (!fBufferRef) {
00911 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
00912 return 0;
00913 }
00914 if (GetFile()==0) return 0;
00915 fBufferRef->SetParent(GetFile());
00916 fBufferRef->SetPidOffset(fPidOffset);
00917
00918 if (fObjlen > fNbytes-fKeylen) {
00919 fBuffer = new char[fNbytes];
00920 ReadFile();
00921 memcpy(fBufferRef->Buffer(),fBuffer,fKeylen);
00922 } else {
00923 fBuffer = fBufferRef->Buffer();
00924 ReadFile();
00925 }
00926
00927
00928 fBufferRef->SetBufferOffset(sizeof(fNbytes));
00929 Version_t kvers = fBufferRef->ReadVersion();
00930
00931 fBufferRef->SetBufferOffset(fKeylen);
00932 TClass *cl = TClass::GetClass(fClassName.Data());
00933 TClass *clOnfile = 0;
00934 if (!cl) {
00935 Error("ReadObjectAny", "Unknown class %s", fClassName.Data());
00936 return 0;
00937 }
00938 Int_t baseOffset = 0;
00939 if (expectedClass) {
00940
00941 baseOffset = cl->GetBaseClassOffset(expectedClass);
00942 if (baseOffset == -1) {
00943
00944
00945 if (!expectedClass->GetSchemaRules() ||
00946 !expectedClass->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()))
00947 {
00948
00949 return 0;
00950 }
00951 baseOffset = 0;
00952 clOnfile = cl;
00953 cl = const_cast<TClass*>(expectedClass);
00954 Info("ReadObjectAny","Using Converter StreamerInfo from %s to %s",clOnfile->GetName(),expectedClass->GetName());
00955 }
00956 if (cl->GetClassInfo() && !expectedClass->GetClassInfo()) {
00957
00958 Warning("ReadObjectAny",
00959 "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
00960 cl->GetName(),expectedClass->GetName());
00961 }
00962 }
00963
00964
00965 void *pobj = cl->New();
00966 if (!pobj) {
00967 Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data());
00968 return 0;
00969 }
00970
00971 if (kvers > 1)
00972 fBufferRef->MapObject(pobj,cl);
00973
00974 if (fObjlen > fNbytes-fKeylen) {
00975 char *objbuf = fBufferRef->Buffer() + fKeylen;
00976 UChar_t *bufcur = (UChar_t *)&fBuffer[fKeylen];
00977 Int_t nin, nout, nbuf;
00978 Int_t noutot = 0;
00979 while (1) {
00980 Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
00981 if (hc!=0) break;
00982 R__unzip(&nin, bufcur, &nbuf, objbuf, &nout);
00983 if (!nout) break;
00984 noutot += nout;
00985 if (noutot >= fObjlen) break;
00986 bufcur += nin;
00987 objbuf += nout;
00988 }
00989 if (nout) {
00990 cl->Streamer((void*)pobj, *fBufferRef, clOnfile);
00991 delete [] fBuffer;
00992 } else {
00993 delete [] fBuffer;
00994 cl->Destructor(pobj);
00995 pobj = 0;
00996 goto CLEAR;
00997 }
00998 } else {
00999 cl->Streamer((void*)pobj, *fBufferRef, clOnfile);
01000 }
01001
01002 if (cl->InheritsFrom(TObject::Class())) {
01003 baseOffset = cl->GetBaseClassOffset(TObject::Class());
01004 if (baseOffset==-1) {
01005 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
01006 fClassName.Data());
01007 }
01008 TObject *tobj = (TObject*)( ((char*)pobj) +baseOffset);
01009
01010
01011 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
01012
01013 if (cl->InheritsFrom(TDirectoryFile::Class())) {
01014 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
01015 dir->SetName(GetName());
01016 dir->SetTitle(GetTitle());
01017 dir->SetMother(fMotherDir);
01018 fMotherDir->Append(dir);
01019 }
01020 }
01021
01022 {
01023
01024 ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
01025 if (addfunc) {
01026 addfunc(pobj, fMotherDir);
01027 }
01028 }
01029
01030 CLEAR:
01031 delete fBufferRef;
01032 fBufferRef = 0;
01033 fBuffer = 0;
01034
01035 return ( ((char*)pobj) + baseOffset );
01036 }
01037
01038
01039 Int_t TKey::Read(TObject *obj)
01040 {
01041
01042
01043
01044
01045
01046 if (!obj || (GetFile()==0)) return 0;
01047
01048 fBufferRef = new TBufferFile(TBuffer::kRead, fObjlen+fKeylen);
01049 fBufferRef->SetParent(GetFile());
01050 fBufferRef->SetPidOffset(fPidOffset);
01051
01052 if (fVersion > 1)
01053 fBufferRef->MapObject(obj);
01054
01055 if (fObjlen > fNbytes-fKeylen) {
01056 fBuffer = new char[fNbytes];
01057 ReadFile();
01058 memcpy(fBufferRef->Buffer(),fBuffer,fKeylen);
01059 } else {
01060 fBuffer = fBufferRef->Buffer();
01061 ReadFile();
01062 }
01063 fBufferRef->SetBufferOffset(fKeylen);
01064 if (fObjlen > fNbytes-fKeylen) {
01065 char *objbuf = fBufferRef->Buffer() + fKeylen;
01066 UChar_t *bufcur = (UChar_t *)&fBuffer[fKeylen];
01067 Int_t nin, nout, nbuf;
01068 Int_t noutot = 0;
01069 while (1) {
01070 Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
01071 if (hc!=0) break;
01072 R__unzip(&nin, bufcur, &nbuf, objbuf, &nout);
01073 if (!nout) break;
01074 noutot += nout;
01075 if (noutot >= fObjlen) break;
01076 bufcur += nin;
01077 objbuf += nout;
01078 }
01079 if (nout) obj->Streamer(*fBufferRef);
01080 delete [] fBuffer;
01081 } else {
01082 obj->Streamer(*fBufferRef);
01083 }
01084 delete fBufferRef;
01085 fBufferRef = 0;
01086 fBuffer = 0;
01087 return fNbytes;
01088 }
01089
01090
01091 void TKey::ReadBuffer(char *&buffer)
01092 {
01093
01094
01095
01096 ReadKeyBuffer(buffer);
01097
01098 if (!gROOT->ReadingObject() && gDirectory) {
01099 if (fSeekPdir != gDirectory->GetSeekDir()) gDirectory->AppendKey(this);
01100 }
01101 }
01102
01103
01104 void TKey::ReadKeyBuffer(char *&buffer)
01105 {
01106
01107
01108 frombuf(buffer, &fNbytes);
01109 Version_t version;
01110 frombuf(buffer,&version);
01111 fVersion = (Int_t)version;
01112 frombuf(buffer, &fObjlen);
01113 fDatime.ReadBuffer(buffer);
01114 frombuf(buffer, &fKeylen);
01115 frombuf(buffer, &fCycle);
01116 if (fVersion > 1000) {
01117 frombuf(buffer, &fSeekKey);
01118
01119
01120
01121
01122
01123
01124
01125
01126 Long64_t pdir;
01127 frombuf(buffer, &pdir);
01128 fPidOffset = pdir >> kPidOffsetShift;
01129 fSeekPdir = pdir & kPidOffsetMask;
01130 } else {
01131 Int_t seekkey,seekdir;
01132 frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey;
01133 frombuf(buffer, &seekdir); fSeekPdir= (Long64_t)seekdir;
01134 }
01135 fClassName.ReadBuffer(buffer);
01136
01137 if (fClassName == "TDirectory") fClassName = "TDirectoryFile";
01138
01139 fName.ReadBuffer(buffer);
01140 fTitle.ReadBuffer(buffer);
01141 }
01142
01143
01144 void TKey::ReadFile()
01145 {
01146
01147
01148 TFile* f = GetFile();
01149 if (f==0) return;
01150
01151 Int_t nsize = fNbytes;
01152 f->Seek(fSeekKey);
01153 #if 0
01154 for (Int_t i = 0; i < nsize; i += kMAXFILEBUFFER) {
01155 int nb = kMAXFILEBUFFER;
01156 if (i+nb > nsize) nb = nsize - i;
01157 f->ReadBuffer(fBuffer+i,nb);
01158 }
01159 #else
01160 f->ReadBuffer(fBuffer,nsize);
01161 #endif
01162 if (gDebug) {
01163 cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<endl;
01164 }
01165 }
01166
01167
01168 void TKey::SetParent(const TObject *parent)
01169 {
01170
01171
01172 if (fBufferRef) fBufferRef->SetParent((TObject*)parent);
01173 }
01174
01175
01176 void TKey::Reset()
01177 {
01178
01179
01180 fPidOffset = 0;
01181 fNbytes = 0;
01182 fBuffer = 0;
01183 fObjlen = 0;
01184 fCycle = 0;
01185 fSeekPdir = 0;
01186 fSeekKey = 0;
01187 fLeft = 0;
01188 fDatime = (UInt_t)0;
01189
01190
01191
01192 keyAbsNumber++; SetUniqueID(keyAbsNumber);
01193 }
01194
01195
01196 Int_t TKey::Sizeof() const
01197 {
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8;
01209 nbytes += fDatime.Sizeof();
01210 nbytes += fClassName.Sizeof();
01211 nbytes += fName.Sizeof();
01212 nbytes += fTitle.Sizeof();
01213 return nbytes;
01214 }
01215
01216
01217 void TKey::Streamer(TBuffer &b)
01218 {
01219
01220
01221 Version_t version;
01222 if (b.IsReading()) {
01223 b >> fNbytes;
01224 b >> version; fVersion = (Int_t)version;
01225 b >> fObjlen;
01226 fDatime.Streamer(b);
01227 b >> fKeylen;
01228 b >> fCycle;
01229 if (fVersion > 1000) {
01230 b >> fSeekKey;
01231
01232
01233
01234
01235
01236
01237
01238
01239 Long64_t pdir;
01240 b >> pdir;
01241 fPidOffset = pdir >> kPidOffsetShift;
01242 fSeekPdir = pdir & kPidOffsetMask;
01243 } else {
01244 Int_t seekkey, seekdir;
01245 b >> seekkey; fSeekKey = (Long64_t)seekkey;
01246 b >> seekdir; fSeekPdir= (Long64_t)seekdir;
01247 }
01248 fClassName.Streamer(b);
01249 fName.Streamer(b);
01250 fTitle.Streamer(b);
01251 if (fKeylen < 0) {
01252 Error("Streamer","The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero",fKeylen);
01253 MakeZombie();
01254 fKeylen = 0;
01255 }
01256 if (fObjlen < 0) {
01257 Error("Streamer","The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero",fObjlen);
01258 MakeZombie();
01259 fObjlen = 0;
01260 }
01261 if (fNbytes < 0) {
01262 Error("Streamer","The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero",fNbytes);
01263 MakeZombie();
01264 fNbytes = 0;
01265 }
01266
01267
01268 } else {
01269 b << fNbytes;
01270 version = (Version_t)fVersion;
01271 b << version;
01272 b << fObjlen;
01273 if (fDatime.Get() == 0) fDatime.Set();
01274 fDatime.Streamer(b);
01275 b << fKeylen;
01276 b << fCycle;
01277 if (fVersion > 1000) {
01278 b << fSeekKey;
01279
01280
01281
01282
01283
01284
01285
01286
01287 Long64_t pdir = (((Long64_t)fPidOffset)<<kPidOffsetShift) | (kPidOffsetMask & fSeekPdir);
01288 b << pdir;
01289 } else {
01290 b << (Int_t)fSeekKey;
01291 b << (Int_t)fSeekPdir;
01292 }
01293 fClassName.Streamer(b);
01294 fName.Streamer(b);
01295 fTitle.Streamer(b);
01296 }
01297 }
01298
01299
01300 Int_t TKey::WriteFile(Int_t cycle, TFile* f)
01301 {
01302
01303
01304
01305
01306 if (!f) f = GetFile();
01307 if (!f) return -1;
01308
01309 Int_t nsize = fNbytes;
01310 char *buffer = fBuffer;
01311 if (cycle) {
01312 fCycle = cycle;
01313 FillBuffer(buffer);
01314 buffer = fBuffer;
01315 }
01316
01317 if (fLeft > 0) nsize += sizeof(Int_t);
01318 f->Seek(fSeekKey);
01319 #if 0
01320 for (Int_t i=0;i<nsize;i+=kMAXFILEBUFFER) {
01321 Int_t nb = kMAXFILEBUFFER;
01322 if (i+nb > nsize) nb = nsize - i;
01323 f->WriteBuffer(buffer,nb);
01324 buffer += nb;
01325 }
01326 #else
01327 Bool_t result = f->WriteBuffer(buffer,nsize);
01328 #endif
01329
01330
01331 if (gDebug) {
01332 cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
01333 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<endl;
01334 }
01335
01336 DeleteBuffer();
01337 return result==kTRUE ? -1 : nsize;
01338 }
01339
01340
01341 Int_t TKey::WriteFileKeepBuffer(TFile *f)
01342 {
01343
01344
01345
01346
01347 if (!f) f = GetFile();
01348 if (!f) return -1;
01349
01350 Int_t nsize = fNbytes;
01351 char *buffer = fBuffer;
01352
01353 if (fLeft > 0) nsize += sizeof(Int_t);
01354 f->Seek(fSeekKey);
01355 #if 0
01356 for (Int_t i=0;i<nsize;i+=kMAXFILEBUFFER) {
01357 Int_t nb = kMAXFILEBUFFER;
01358 if (i+nb > nsize) nb = nsize - i;
01359 f->WriteBuffer(buffer,nb);
01360 buffer += nb;
01361 }
01362 #else
01363 Bool_t result = f->WriteBuffer(buffer,nsize);
01364 #endif
01365
01366
01367 if (gDebug) {
01368 cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
01369 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<endl;
01370 }
01371
01372 return result==kTRUE ? -1 : nsize;
01373 }
01374
01375
01376 const char *TKey::GetIconName() const
01377 {
01378
01379
01380 return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0);
01381 }
01382
01383
01384 const char *TKey::GetTitle() const
01385 {
01386
01387
01388 if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) {
01389 static TString ret;
01390 int start = fTitle.Index("/*") + 3;
01391 int stop = fTitle.Index("*/") - 1;
01392 ret = fTitle(start, stop - start);
01393 return ret.Data();
01394 }
01395 return fTitle.Data();
01396 }