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
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 #include <stdlib.h>
00098 #include "TClonesArray.h"
00099 #include "TError.h"
00100 #include "TROOT.h"
00101 #include "TClass.h"
00102 #include "TObjectTable.h"
00103
00104
00105 ClassImp(TClonesArray)
00106
00107
00108 TClonesArray::TClonesArray() : TObjArray()
00109 {
00110
00111
00112 fClass = 0;
00113 fKeep = 0;
00114 }
00115
00116
00117 TClonesArray::TClonesArray(const char *classname, Int_t s, Bool_t) : TObjArray(s)
00118 {
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 fKeep = 0;
00139 SetClass(classname,s);
00140 }
00141
00142
00143 TClonesArray::TClonesArray(const TClass *cl, Int_t s, Bool_t) : TObjArray(s)
00144 {
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 fKeep = 0;
00165 SetClass(cl,s);
00166 }
00167
00168
00169 TClonesArray::TClonesArray(const TClonesArray& tc): TObjArray(tc)
00170 {
00171
00172
00173 fKeep = new TObjArray(tc.fSize);
00174 fClass = tc.fClass;
00175
00176 BypassStreamer(kTRUE);
00177
00178 for (Int_t i = 0; i < fSize; i++) {
00179 if (tc.fCont[i]) fCont[i] = tc.fCont[i]->Clone();
00180 fKeep->fCont[i] = fCont[i];
00181 }
00182 }
00183
00184
00185 TClonesArray& TClonesArray::operator=(const TClonesArray& tc)
00186 {
00187
00188
00189 if (this == &tc) return *this;
00190
00191 if (fClass != tc.fClass) {
00192 Error("operator=", "cannot copy TClonesArray's when classes are different");
00193 return *this;
00194 }
00195
00196 if (tc.fSize > fSize)
00197 Expand(TMath::Max(tc.fSize, GrowBy(fSize)));
00198
00199 Int_t i;
00200
00201 for (i = 0; i < fSize; i++)
00202 if (fKeep->fCont[i]) {
00203 if (TObject::GetObjectStat() && gObjectTable)
00204 gObjectTable->RemoveQuietly(fKeep->fCont[i]);
00205 ::operator delete(fKeep->fCont[i]);
00206 fKeep->fCont[i] = 0;
00207 fCont[i] = 0;
00208 }
00209
00210 BypassStreamer(kTRUE);
00211
00212 for (i = 0; i < tc.fSize; i++) {
00213 if (tc.fCont[i]) fKeep->fCont[i] = tc.fCont[i]->Clone();
00214 fCont[i] = fKeep->fCont[i];
00215 }
00216
00217 fLast = tc.fSize - 1;
00218 Changed();
00219 return *this;
00220 }
00221
00222
00223 TClonesArray::~TClonesArray()
00224 {
00225
00226
00227 if (fKeep) {
00228 for (Int_t i = 0; i < fKeep->fSize; i++) {
00229 TObject* p = fKeep->fCont[i];
00230 if (p && p->TestBit(kNotDeleted)) {
00231
00232 fClass->Destructor(p);
00233 fKeep->fCont[i] = 0;
00234 } else {
00235
00236
00237
00238 if (TObject::GetObjectStat() && gObjectTable) {
00239 gObjectTable->RemoveQuietly(p);
00240 }
00241 ::operator delete(p);
00242 fKeep->fCont[i] = 0;
00243 }
00244 }
00245 }
00246 SafeDelete(fKeep);
00247
00248
00249 SetOwner(kFALSE);
00250 }
00251
00252
00253 void TClonesArray::BypassStreamer(Bool_t bypass)
00254 {
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 if (bypass)
00281 SetBit(kBypassStreamer);
00282 else
00283 ResetBit(kBypassStreamer);
00284 }
00285
00286
00287 void TClonesArray::Compress()
00288 {
00289
00290
00291 Int_t j = 0, je = 0;
00292
00293 TObject **tmp = new TObject* [fSize];
00294
00295 for (Int_t i = 0; i < fSize; i++) {
00296 if (fCont[i]) {
00297 fCont[j] = fCont[i];
00298 fKeep->fCont[j] = fKeep->fCont[i];
00299 j++;
00300 } else {
00301 tmp[je] = fKeep->fCont[i];
00302 je++;
00303 }
00304 }
00305
00306 fLast = j - 1;
00307
00308 Int_t jf = 0;
00309 for ( ; j < fSize; j++) {
00310 fCont[j] = 0;
00311 fKeep->fCont[j] = tmp[jf];
00312 jf++;
00313 }
00314
00315 delete [] tmp;
00316
00317 R__ASSERT(je == jf);
00318 }
00319
00320
00321 void TClonesArray::Clear(Option_t *option)
00322 {
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 if (option && option[0] == 'C') {
00334 const char *cplus = strstr(option,"+");
00335 Int_t n = GetEntriesFast();
00336 for (Int_t i = 0; i < n; i++) {
00337 TObject *obj = UncheckedAt(i);
00338 if (obj) {
00339 if (cplus) obj->Clear(cplus+1);
00340 else obj->Clear();
00341 }
00342 }
00343 }
00344
00345
00346 SetOwner(kFALSE);
00347
00348 TObjArray::Clear();
00349 }
00350
00351
00352 void TClonesArray::Delete(Option_t *)
00353 {
00354
00355
00356
00357
00358 Long_t dtoronly = TObject::GetDtorOnly();
00359 for (Int_t i = 0; i < fSize; i++) {
00360 if (fCont[i] && fCont[i]->TestBit(kNotDeleted)) {
00361
00362
00363
00364 TObject::SetDtorOnly(fCont[i]);
00365 delete fCont[i];
00366 }
00367 }
00368
00369 TObject::SetDtorOnly((void*)dtoronly);
00370
00371
00372 SetOwner(kFALSE);
00373
00374 TObjArray::Clear();
00375 }
00376
00377
00378 void TClonesArray::Expand(Int_t newSize)
00379 {
00380
00381
00382 if (newSize < 0) {
00383 Error ("Expand", "newSize must be positive (%d)", newSize);
00384 return;
00385 }
00386 if (newSize == fSize)
00387 return;
00388 if (newSize < fSize) {
00389
00390
00391 for (int i = newSize; i < fSize; i++)
00392 if (fKeep->fCont[i]) {
00393 if (TObject::GetObjectStat() && gObjectTable)
00394 gObjectTable->RemoveQuietly(fKeep->fCont[i]);
00395 ::operator delete(fKeep->fCont[i]);
00396 fKeep->fCont[i] = 0;
00397 }
00398 }
00399
00400 TObjArray::Expand(newSize);
00401 fKeep->Expand(newSize);
00402 }
00403
00404
00405 void TClonesArray::ExpandCreate(Int_t n)
00406 {
00407
00408
00409
00410
00411
00412
00413
00414 if (n < 0) {
00415 Error("ExpandCreate", "n must be positive (%d)", n);
00416 return ;
00417 }
00418 if (n > fSize)
00419 Expand(TMath::Max(n, GrowBy(fSize)));
00420
00421 Int_t i;
00422 for (i = 0; i < n; i++) {
00423 if (!fKeep->fCont[i]) {
00424 fKeep->fCont[i] = (TObject*)fClass->New();
00425 } else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
00426
00427 fClass->New(fKeep->fCont[i]);
00428 }
00429 fCont[i] = fKeep->fCont[i];
00430 }
00431
00432 for (i = n; i < fSize; i++)
00433 if (fKeep->fCont[i]) {
00434 if (TObject::GetObjectStat() && gObjectTable)
00435 gObjectTable->RemoveQuietly(fKeep->fCont[i]);
00436 ::operator delete(fKeep->fCont[i]);
00437 fKeep->fCont[i] = 0;
00438 fCont[i] = 0;
00439 }
00440
00441 fLast = n - 1;
00442 Changed();
00443 }
00444
00445
00446 void TClonesArray::ExpandCreateFast(Int_t n)
00447 {
00448
00449
00450
00451
00452
00453
00454
00455
00456 if (n > fSize)
00457 Expand(TMath::Max(n, GrowBy(fSize)));
00458
00459 Int_t i;
00460 for (i = 0; i < n; i++) {
00461 if (!fKeep->fCont[i]) {
00462 fKeep->fCont[i] = (TObject*)fClass->New();
00463 } else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
00464
00465 fClass->New(fKeep->fCont[i]);
00466 }
00467 fCont[i] = fKeep->fCont[i];
00468 }
00469 fLast = n - 1;
00470 Changed();
00471 }
00472
00473
00474 TObject *TClonesArray::RemoveAt(Int_t idx)
00475 {
00476
00477
00478 if (!BoundsOk("RemoveAt", idx)) return 0;
00479
00480 int i = idx-fLowerBound;
00481
00482 if (fCont[i] && fCont[i]->TestBit(kNotDeleted)) {
00483
00484
00485
00486 Long_t dtoronly = TObject::GetDtorOnly();
00487 TObject::SetDtorOnly(fCont[i]);
00488 delete fCont[i];
00489 TObject::SetDtorOnly((void*)dtoronly);
00490 }
00491
00492 if (fCont[i]) {
00493 fCont[i] = 0;
00494
00495 if (i == fLast)
00496 do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
00497 Changed();
00498 }
00499
00500 return 0;
00501 }
00502
00503
00504 TObject *TClonesArray::Remove(TObject *obj)
00505 {
00506
00507
00508 if (!obj) return 0;
00509
00510 Int_t i = IndexOf(obj) - fLowerBound;
00511
00512 if (i == -1) return 0;
00513
00514 if (fCont[i] && fCont[i]->TestBit(kNotDeleted)) {
00515
00516
00517
00518 Long_t dtoronly = TObject::GetDtorOnly();
00519 TObject::SetDtorOnly(fCont[i]);
00520 delete fCont[i];
00521 TObject::SetDtorOnly((void*)dtoronly);
00522 }
00523
00524 fCont[i] = 0;
00525
00526 if (i == fLast)
00527 do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
00528 Changed();
00529 return obj;
00530 }
00531
00532
00533 void TClonesArray::RemoveRange(Int_t idx1, Int_t idx2)
00534 {
00535
00536
00537 if (!BoundsOk("RemoveRange", idx1)) return;
00538 if (!BoundsOk("RemoveRange", idx2)) return;
00539
00540 Long_t dtoronly = TObject::GetDtorOnly();
00541
00542 idx1 -= fLowerBound;
00543 idx2 -= fLowerBound;
00544
00545 Bool_t change = kFALSE;
00546 for (TObject **obj=fCont+idx1; obj<=fCont+idx2; obj++) {
00547 if (!*obj) continue;
00548 if ((*obj)->TestBit(kNotDeleted)) {
00549
00550
00551
00552 TObject::SetDtorOnly(*obj);
00553 delete *obj;
00554 }
00555 *obj = 0;
00556 change = kTRUE;
00557 }
00558
00559 TObject::SetDtorOnly((void*)dtoronly);
00560
00561
00562 if (change) Changed();
00563 if (idx1 < fLast || fLast > idx2) return;
00564 do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
00565 }
00566
00567
00568 void TClonesArray::SetClass(const TClass *cl, Int_t s)
00569 {
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 if (fKeep) {
00590 Error("SetClass", "TClonesArray already initialized with another class");
00591 return;
00592 }
00593 fClass = (TClass*)cl;
00594 if (!fClass) {
00595 MakeZombie();
00596 Error("SetClass", "called with a null pointer");
00597 return;
00598 }
00599 const char *classname = fClass->GetName();
00600 if (!fClass->InheritsFrom(TObject::Class())) {
00601 MakeZombie();
00602 Error("SetClass", "%s does not inherit from TObject", classname);
00603 return;
00604 }
00605 Int_t nch = strlen(classname)+2;
00606 char *name = new char[nch];
00607 snprintf(name,nch, "%ss", classname);
00608 SetName(name);
00609 delete [] name;
00610
00611 fKeep = new TObjArray(s);
00612
00613 BypassStreamer(kTRUE);
00614 }
00615
00616
00617 void TClonesArray::SetClass(const char *classname, Int_t s)
00618 {
00619
00620
00621 SetClass(TClass::GetClass(classname),s);
00622 }
00623
00624
00625
00626 void TClonesArray::SetOwner(Bool_t )
00627 {
00628
00629
00630
00631
00632
00633 }
00634
00635
00636 void TClonesArray::Sort(Int_t upto)
00637 {
00638
00639
00640
00641 Int_t nentries = GetAbsLast()+1;
00642 if (nentries <= 0 || fSorted) return;
00643 for (Int_t i = 0; i < fSize; i++)
00644 if (fCont[i]) {
00645 if (!fCont[i]->IsSortable()) {
00646 Error("Sort", "objects in array are not sortable");
00647 return;
00648 }
00649 }
00650
00651 QSort(fCont, fKeep->fCont, 0, TMath::Min(nentries, upto-fLowerBound));
00652
00653 fLast = -2;
00654 fSorted = kTRUE;
00655 }
00656
00657
00658 void TClonesArray::Streamer(TBuffer &b)
00659 {
00660
00661
00662
00663
00664
00665
00666
00667 Int_t nobjects;
00668 char nch;
00669 TString s, classv;
00670 UInt_t R__s, R__c;
00671
00672 if (b.IsReading()) {
00673 Version_t v = b.ReadVersion(&R__s, &R__c);
00674 if (v == 3) {
00675 const Int_t kOldBypassStreamer = BIT(14);
00676 if (TestBit(kOldBypassStreamer)) BypassStreamer();
00677 }
00678 if (v > 2)
00679 TObject::Streamer(b);
00680 if (v > 1)
00681 fName.Streamer(b);
00682 s.Streamer(b);
00683 classv = s;
00684 Int_t clv = 0;
00685 Ssiz_t pos = s.Index(";");
00686 if (pos != kNPOS) {
00687 classv = s(0, pos);
00688 s = s(pos+1, s.Length()-pos-1);
00689 clv = s.Atoi();
00690 }
00691 TClass *cl = TClass::GetClass(classv);
00692 if (!cl) {
00693 printf("TClonesArray::Streamer expecting class %s\n", classv.Data());
00694 b.CheckByteCount(R__s, R__c,TClonesArray::IsA());
00695 return;
00696 }
00697
00698 b >> nobjects;
00699 if (nobjects < 0)
00700 nobjects = -nobjects;
00701 b >> fLowerBound;
00702 if (fClass == 0 && fKeep == 0) {
00703 fClass = cl;
00704 fKeep = new TObjArray(fSize);
00705 Expand(nobjects);
00706 }
00707 if (cl != fClass) {
00708 fClass = cl;
00709
00710
00711
00712
00713
00714 }
00715
00716
00717 if (fKeep->GetSize() < nobjects)
00718 Expand(nobjects);
00719
00720
00721 Int_t oldLast = fLast;
00722 fLast = nobjects-1;
00723
00724
00725 if (CanBypassStreamer() && !b.TestBit(TBuffer::kCannotHandleMemberWiseStreaming)) {
00726 for (Int_t i = 0; i < nobjects; i++) {
00727 if (!fKeep->fCont[i]) {
00728 fKeep->fCont[i] = (TObject*)fClass->New();
00729 } else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
00730
00731 fClass->New(fKeep->fCont[i]);
00732 }
00733
00734 fCont[i] = fKeep->fCont[i];
00735 }
00736
00737 b.ReadClones(this,nobjects,clv);
00738
00739 } else {
00740 for (Int_t i = 0; i < nobjects; i++) {
00741 b >> nch;
00742 if (nch) {
00743 if (!fKeep->fCont[i])
00744 fKeep->fCont[i] = (TObject*)fClass->New();
00745 else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
00746
00747 fClass->New(fKeep->fCont[i]);
00748 }
00749
00750 fCont[i] = fKeep->fCont[i];
00751 b.StreamObject(fKeep->fCont[i]);
00752 }
00753 }
00754 }
00755 for (Int_t i = TMath::Max(nobjects,0); i < oldLast+1; ++i) fCont[i] = 0;
00756 Changed();
00757 b.CheckByteCount(R__s, R__c,TClonesArray::IsA());
00758 } else {
00759
00760
00761
00762
00763 b.ForceWriteInfoClones(this);
00764
00765
00766
00767
00768
00769
00770 Bool_t bypass = kFALSE;
00771 if (b.TestBit(TBuffer::kCannotHandleMemberWiseStreaming)) {
00772 bypass = CanBypassStreamer();
00773 BypassStreamer(kFALSE);
00774 }
00775
00776 R__c = b.WriteVersion(TClonesArray::IsA(), kTRUE);
00777 TObject::Streamer(b);
00778 fName.Streamer(b);
00779 s.Form("%s;%d", fClass->GetName(), fClass->GetClassVersion());
00780 s.Streamer(b);
00781 nobjects = GetEntriesFast();
00782 b << nobjects;
00783 b << fLowerBound;
00784 if (CanBypassStreamer()) {
00785 b.WriteClones(this,nobjects);
00786 } else {
00787 for (Int_t i = 0; i < nobjects; i++) {
00788 if (!fCont[i]) {
00789 nch = 0;
00790 b << nch;
00791 } else {
00792 nch = 1;
00793 b << nch;
00794 b.StreamObject(fCont[i]);
00795 }
00796 }
00797 }
00798 b.SetByteCount(R__c, kTRUE);
00799
00800 if (bypass)
00801 BypassStreamer();
00802 }
00803 }
00804
00805
00806 TObject *&TClonesArray::operator[](Int_t idx)
00807 {
00808
00809
00810
00811
00812
00813
00814
00815
00816 if (idx < 0) {
00817 Error("operator[]", "out of bounds at %d in %lx", idx, (Long_t)this);
00818 return fCont[0];
00819 }
00820 if (!fClass) {
00821 Error("operator[]", "invalid class specified in TClonesArray ctor");
00822 return fCont[0];
00823 }
00824 if (idx >= fSize)
00825 Expand(TMath::Max(idx+1, GrowBy(fSize)));
00826
00827 if (!fKeep->fCont[idx])
00828 fKeep->fCont[idx] = (TObject*) TStorage::ObjectAlloc(fClass->Size());
00829
00830 fCont[idx] = fKeep->fCont[idx];
00831
00832 fLast = TMath::Max(idx, GetAbsLast());
00833 Changed();
00834
00835 return fCont[idx];
00836 }
00837
00838
00839 TObject *TClonesArray::operator[](Int_t idx) const
00840 {
00841
00842
00843 if (idx < 0 || idx >= fSize) {
00844 Error("operator[]", "out of bounds at %d in %lx", idx, (Long_t)this);
00845 return 0;
00846 }
00847
00848 return fCont[idx];
00849 }
00850
00851
00852 TObject *TClonesArray::New(Int_t idx)
00853 {
00854
00855
00856
00857 if (idx < 0) {
00858 Error("New", "out of bounds at %d in %lx", idx, (Long_t)this);
00859 return 0;
00860 }
00861 if (!fClass) {
00862 Error("New", "invalid class specified in TClonesArray ctor");
00863 return 0;
00864 }
00865
00866 return (TObject *)fClass->New(operator[](idx));
00867 }
00868
00869
00870
00871
00872
00873
00874
00875 void TClonesArray::AbsorbObjects(TClonesArray* tc)
00876 {
00877
00878
00879
00880
00881
00882
00883 if(tc == NULL || tc == this || tc->GetEntriesFast() == 0) return;
00884 if (fClass != tc->fClass) {
00885 Error("AbsorbObjects", "cannot absorb objects when classes are different");
00886 return;
00887 }
00888
00889
00890 bool wasSorted = IsSorted() && tc->IsSorted() &&
00891 (Last() == NULL || Last()->Compare(tc->First()) == -1);
00892
00893
00894 Int_t oldSize = GetEntriesFast();
00895 Int_t newSize = oldSize + tc->GetEntriesFast();
00896 if(newSize > fSize) Expand(newSize);
00897
00898
00899 for(Int_t i = 0; i <= tc->GetEntriesFast(); i++) {
00900 fCont[oldSize+i] = tc->fCont[i];
00901 (*fKeep)[oldSize+i] = (*(tc->fKeep))[i];
00902 tc->fCont[i] = NULL;
00903 (*(tc->fKeep))[i] = NULL;
00904 }
00905
00906
00907 fLast = newSize-1;
00908 tc->fLast = -1;
00909 if(!wasSorted) Changed();
00910 }
00911
00912
00913
00914 void TClonesArray::MultiSort(Int_t nTCs, TClonesArray** tcs, Int_t upto)
00915 {
00916
00917
00918
00919
00920 Int_t nentries = GetAbsLast()+1;
00921 if (nentries <= 1 || fSorted) return;
00922 bool sortedCheck = true;
00923 for (Int_t i = 0; i < fSize; i++) {
00924 if (fCont[i]) {
00925 if (!fCont[i]->IsSortable()) {
00926 Error("MultiSort", "objects in array are not sortable");
00927 return;
00928 }
00929 }
00930 if (sortedCheck && i > 1) {
00931 if(ObjCompare(fCont[i], fCont[i-1]) < 0) sortedCheck = false;
00932 }
00933 }
00934 if (sortedCheck) {
00935 fSorted = true;
00936 return;
00937 }
00938
00939 for (int i=0; i<nTCs; i++) {
00940 if (tcs[i] == this) {
00941 Error("MultiSort", "tcs[%d] = \"this\"", i);
00942 return;
00943 }
00944 if (tcs[i]->GetEntriesFast() != GetEntriesFast()) {
00945 Error("MultiSort", "tcs[%d] has length %d != length of this (%d)",
00946 i, tcs[i]->GetEntriesFast(), this->GetEntriesFast());
00947 return;
00948 }
00949 }
00950
00951 int nBs = nTCs*2+1;
00952 TObject*** b = new TObject**[nBs];
00953 for (int i = 0; i < nTCs; i++) {
00954 b[2*i] = tcs[i]->fCont;
00955 b[2*i+1] = tcs[i]->fKeep->fCont;
00956 }
00957 b[nBs-1] = fKeep->fCont;
00958 QSort(fCont, nBs, b, 0, TMath::Min(nentries, upto-fLowerBound));
00959 delete [] b;
00960
00961 fLast = -2;
00962 fSorted = kTRUE;
00963 }