/*
<img src=gif/tobjarray.gif>
*/
//End_Html
#include "TObjArray.h"
#include "TError.h"
#include "TROOT.h"
#include <stdlib.h>
ClassImp(TObjArray)
TObjArray::TObjArray(Int_t s, Int_t lowerBound)
{
   
   
   
   if (s < 0) {
      Warning("TObjArray", "size (%d) < 0", s);
      s = TCollection::kInitCapacity;
   } else if (s == 0)
      s = TCollection::kInitCapacity;
   fCont = 0;
   Init(s, lowerBound);
}
TObjArray::TObjArray(const TObjArray &a) : TSeqCollection()
{
   
   fCont = 0;
   Init(a.fSize, a.fLowerBound);
   for (Int_t i = 0; i < fSize; i++)
      fCont[i] = a.fCont[i];
   fLast = a.fLast;
   fName = a.fName;
}
TObjArray::~TObjArray()
{
   
   
   if (IsOwner())
      Delete();
   TStorage::Dealloc(fCont);
   fCont = 0;
   fSize = 0;
}
TObjArray& TObjArray::operator=(const TObjArray &a)
{
   
   if (this != &a) {
      if (IsOwner())
         Delete();
      SetOwner(kFALSE);
      Init(a.fSize, a.fLowerBound);
      for (Int_t i = 0; i < fSize; i++)
         fCont[i] = a.fCont[i];
      fLast = a.fLast;
      fName = a.fName;
   }
   return *this;
}
TObject *&TObjArray::operator[](Int_t i)
{
   
   
   int j = i-fLowerBound;
   if (j >= 0 && j < fSize) {
      fLast = TMath::Max(j, GetAbsLast());
      Changed();
      return fCont[j];
   }
   BoundsOk("operator[]", i);
   fLast = -2; 
   return fCont[0];
}
TObject *TObjArray::operator[](Int_t i) const
{
   
   int j = i-fLowerBound;
   if (j >= 0 && j < fSize) return fCont[j];
   BoundsOk("operator[] const", i);
   return 0;
}
void TObjArray::AddFirst(TObject *obj)
{
   
   
   
   fCont[0] = obj;
   Changed();
}
void TObjArray::AddLast(TObject *obj)
{
   
   
   AddAtAndExpand(obj, GetAbsLast()+1+fLowerBound);
}
void TObjArray::AddBefore(const TObject *before, TObject *obj)
{
   
   
   
   
   if (!before)
      AddFirst(obj);
   else {
      Int_t idx = IndexOf(before) - fLowerBound;
      if (idx == -1) {
         Error("AddBefore", "before not found, object not added");
         return;
      }
      if (idx == 0) {
         Error("AddBefore", "cannot add before lowerbound (%d)", fLowerBound);
         return;
      }
      AddAt(obj, idx+fLowerBound-1);
   }
}
void TObjArray::AddAfter(const TObject *after, TObject *obj)
{
   
   
   
   
   if (!after)
      AddLast(obj);
   else {
      Int_t idx = IndexOf(after) - fLowerBound;
      if (idx == -1) {
         Error("AddAfter", "after not found, object not added");
         return;
      }
      AddAtAndExpand(obj, idx+fLowerBound+1);
   }
}
void TObjArray::AddAtAndExpand(TObject *obj, Int_t idx)
{
   
   
   if (idx < fLowerBound) {
      Error("AddAt", "out of bounds at %d in %lx", idx, this);
      return;
   }
   if (idx-fLowerBound >= fSize)
      Expand(TMath::Max(idx-fLowerBound+1, GrowBy(fSize)));
   fCont[idx-fLowerBound] = obj;
   fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
   Changed();
}
void TObjArray::AddAt(TObject *obj, Int_t idx)
{
   
   
   if (!BoundsOk("AddAt", idx)) return;
   fCont[idx-fLowerBound] = obj;
   fLast = TMath::Max(idx-fLowerBound, GetAbsLast());
   Changed();
}
Int_t  TObjArray::AddAtFree(TObject *obj)
{
   
   
   if (Last()) {    
      Int_t i;
      for (i = 0; i < fSize; i++)
         if (!fCont[i]) {         
            fCont[i] = obj;
            fLast = TMath::Max(i, GetAbsLast());
            Changed();
            return i+fLowerBound;
         }
   }
   AddLast(obj);
   return GetLast();
}
TObject *TObjArray::After(const TObject *obj) const
{
   
   if (!obj) return 0;
   Int_t idx = IndexOf(obj) - fLowerBound;
   if (idx == -1 || idx == fSize-1) return 0;
   return fCont[idx+1];
}
TObject *TObjArray::Before(const TObject *obj) const
{
   
   if (!obj) return 0;
   Int_t idx = IndexOf(obj) - fLowerBound;
   if (idx == -1 || idx == 0) return 0;
   return fCont[idx-1];
}
void TObjArray::Clear(Option_t *)
{
   
   
   if (IsOwner())
      Delete();
   else
      Init(fSize, fLowerBound);
}
void TObjArray::Compress()
{
   
   Int_t j = 0;
   for (Int_t i = 0; i < fSize; i++) {
      if (fCont[i]) {
         fCont[j] = fCont[i];
         j++;
      }
   }
   fLast = j - 1;
   for ( ; j < fSize; j++)
      fCont[j] = 0;
}
void TObjArray::Delete(Option_t *)
{
   
   for (Int_t i = 0; i < fSize; i++)
      if (fCont[i] && fCont[i]->IsOnHeap()) {
         TCollection::GarbageCollect(fCont[i]);
         fCont[i] = 0;
      }
   Init(fSize, fLowerBound);
}
void TObjArray::Expand(Int_t newSize)
{
   
   if (newSize < 0) {
      Error ("Expand", "newSize must be positive (%d)", newSize);
      return;
   }
   if (newSize == fSize)
      return;
   if (newSize < fSize) {
      
      for (Int_t j = newSize; j < fSize; j++)
         if (fCont[j]) {
            Error ("Expand", "expand would cut off nonempty entries at %d", j);
            return;
         }
   }
   fCont = (TObject**) TStorage::ReAlloc(fCont, newSize * sizeof(TObject*),
                                         fSize * sizeof(TObject*));
   fSize = newSize;
}
TObject *TObjArray::FindObject(const char *name) const
{
   
   
   
   Int_t nobjects = GetAbsLast()+1;
   for (Int_t i = 0; i < nobjects; ++i) {
      TObject *obj = fCont[i];
      if (obj && 0==strcmp(name, obj->GetName())) return obj;
   }
   return 0;
}
TObject *TObjArray::FindObject(const TObject *iobj) const
{
   
   
   
   
   
   Int_t nobjects = GetAbsLast()+1;
   for (Int_t i = 0; i < nobjects; ++i) {
      TObject *obj = fCont[i];
      if (obj && obj->IsEqual(iobj)) return obj;
   }
   return 0;
}
void TObjArray::Streamer(TBuffer &b)
{
   
   UInt_t R__s, R__c;
   Int_t nobjects;
   if (b.IsReading()) {
      Version_t v = b.ReadVersion(&R__s, &R__c);
      if (v > 2)
         TObject::Streamer(b);
      if (v > 1)
         fName.Streamer(b);
      if (GetEntriesFast() > 0) Clear();
      b >> nobjects;
      b >> fLowerBound;
      if (nobjects >= fSize) Expand(nobjects);
      fLast = -1;
      TObject *obj;
      for (Int_t i = 0; i < nobjects; i++) {
         obj = (TObject*) b.ReadObjectAny(TObject::Class());
         if (obj) {
            fCont[i] = obj;
            fLast = i;
         }
      }
      Changed();
      b.CheckByteCount(R__s, R__c,TObjArray::IsA());
   } else {
      R__c = b.WriteVersion(TObjArray::IsA(), kTRUE);
      TObject::Streamer(b);
      fName.Streamer(b);
      nobjects = GetAbsLast()+1;
      b << nobjects;
      b << fLowerBound;
      for (Int_t i = 0; i < nobjects; i++) {
         b << fCont[i];
      }
      b.SetByteCount(R__c, kTRUE);
   }
}
TObject *TObjArray::First() const
{
   
   return fCont[0];
}
TObject *TObjArray::Last() const
{
   
   if (fLast == -1)
      return 0;
   else
      return fCont[GetAbsLast()];
}
Int_t TObjArray::GetEntries() const
{
   
   
   
   
   
   Int_t cnt = 0;
   for (Int_t i = 0; i < fSize; i++)
      if (fCont[i]) cnt++;
   return cnt;
}
Int_t TObjArray::GetAbsLast() const
{
   
   
   
   
   
   if (fLast == -2) {
      for (Int_t i = fSize-1; i >= 0; i--)
         if (fCont[i]) {
            ((TObjArray*)this)->fLast = i;
            return fLast;
         }
      ((TObjArray*)this)->fLast = -1;
   }
   return fLast;
}
Int_t TObjArray::GetLast() const
{
   
   
   return fLowerBound+GetAbsLast();
}
TObject **TObjArray::GetObjectRef(const TObject *obj) const
{
   
   if (!obj)
      return fCont;
   Int_t index = IndexOf(obj);
   return &fCont[index];
}
Int_t TObjArray::IndexOf(const TObject *obj) const
{
   
   
   
   
   
   Int_t i;
   if (obj) {
      for (i = 0; i < fSize; i++)
         if (fCont[i] && fCont[i]->IsEqual(obj))
            return i+fLowerBound;
   } else {    
      for (i = 0; i < fSize; i++)
         if (!fCont[i])
            return i+fLowerBound;
   }
   return fLowerBound-1;
}
void TObjArray::Init(Int_t s, Int_t lowerBound)
{
   
   if (fCont && fSize != s) {
      TStorage::Dealloc(fCont);
      fCont = 0;
   }
   fSize = s;
   if (!fCont)
      fCont = (TObject**) TStorage::Alloc(fSize*sizeof(TObject*)); 
   memset(fCont, 0, fSize*sizeof(TObject*));
   fLowerBound = lowerBound;
   fLast = -1;
   Changed();
}
TIterator *TObjArray::MakeIterator(Bool_t dir) const
{
   
   return new TObjArrayIter(this, dir);
}
Bool_t TObjArray::OutOfBoundsError(const char *where, Int_t i) const
{
   
   Error(where, "index %d out of bounds (size: %d, this: 0x%08x)", i, fSize, this);
   return kFALSE;
}
void TObjArray::RecursiveRemove(TObject *obj)
{
   
   
   if (!obj) return;
   for (int i = 0; i < fSize; i++) {
      if (fCont[i] && fCont[i]->TestBit(kNotDeleted) && fCont[i]->IsEqual(obj)) {
         fCont[i] = 0;
         
         if (i == fLast)
            do {
               fLast--;
            } while (fLast >= 0 && fCont[fLast] == 0);
         Changed();
      } else if (fCont[i] && fCont[i]->TestBit(kNotDeleted))
         fCont[i]->RecursiveRemove(obj);
   }
}
TObject *TObjArray::RemoveAt(Int_t idx)
{
   
   if (!BoundsOk("RemoveAt", idx)) return 0;
   int i = idx-fLowerBound;
   TObject *obj = 0;
   if (fCont[i]) {
      obj = fCont[i];
      fCont[i] = 0;
      
      if (i == fLast)
         do {
            fLast--;
         } while (fLast >= 0 && fCont[fLast] == 0);
      Changed();
   }
   return obj;
}
TObject *TObjArray::Remove(TObject *obj)
{
   
   if (!obj) return 0;
   Int_t idx = IndexOf(obj) - fLowerBound;
   if (idx == -1) return 0;
   TObject *ob = fCont[idx];
   fCont[idx] = 0;
   
   if (idx == fLast)
      do {
         fLast--;
      } while (fLast >= 0 && fCont[fLast] == 0);
   Changed();
   return ob;
}
void TObjArray::SetLast(Int_t last)
{
   
   
   
   
   
   if (last == -2)
      fLast = -2;
   else if (BoundsOk("SetLast", last))
      fLast = last - fLowerBound;
}
void TObjArray::Randomize(Int_t ntimes)
{
   
   
   
   
   
   
   
   for (Int_t i=0;i<ntimes;i++) {
      for (Int_t j=0;j<fLast;j++) {
#ifdef R__WIN32
         Int_t k = (Int_t)(fLast*rand()/(RAND_MAX+1.0));
#else
         Int_t k = (Int_t)(fLast*random()/(RAND_MAX+1.0));
#endif
         if (k == j) continue;
         TObject *obj = fCont[j];
         fCont[j] = fCont[k];
         fCont[k] = obj;
      }
   }
}
void TObjArray::Sort(Int_t upto)
{
   
   
   if (GetAbsLast() == -1 || fSorted) return;
   for (Int_t i = 0; i < fSize; i++)
      if (fCont[i]) {
         if (!fCont[i]->IsSortable()) {
            Error("Sort", "objects in array are not sortable");
            return;
         }
      }
   QSort(fCont, 0, TMath::Min(fSize, upto-fLowerBound));
   fLast   = -2;
   fSorted = kTRUE;
}
Int_t TObjArray::BinarySearch(TObject *op, Int_t upto)
{
   
   
   Int_t   base, position, last, result = 0;
   TObject *op2;
   if (!op) return -1;
   if (!fSorted) {
      Error("BinarySearch", "array must first be sorted");
      return -1;
   }
   base = 0;
   last = TMath::Min(fSize, upto-fLowerBound) - 1;
   while (last >= base) {
      position = (base+last) / 2;
      op2 = fCont[position];
      if (op2 && (result = op->Compare(op2)) == 0)
         return position + fLowerBound;
      if (!op2 || result < 0)
         last = position-1;
      else
         base = position+1;
   }
   return -1;
}
ClassImp(TObjArrayIter)
TObjArrayIter::TObjArrayIter(const TObjArray *arr, Bool_t dir)
{
   
   
   fArray     = arr;
   fDirection = dir;
   Reset();
}
TObjArrayIter::TObjArrayIter(const TObjArrayIter &iter) : TIterator(iter)
{
   
   fArray     = iter.fArray;
   fDirection = iter.fDirection;
   fCursor    = iter.fCursor;
   fCurCursor = iter.fCurCursor;
}
TIterator &TObjArrayIter::operator=(const TIterator &rhs)
{
   
   if (this != &rhs && rhs.IsA() == TObjArrayIter::Class()) {
      const TObjArrayIter &rhs1 = (const TObjArrayIter &)rhs;
      fArray     = rhs1.fArray;
      fDirection = rhs1.fDirection;
      fCursor    = rhs1.fCursor;
      fCurCursor = rhs1.fCurCursor;
   }
   return *this;
}
TObjArrayIter &TObjArrayIter::operator=(const TObjArrayIter &rhs)
{
   
   if (this != &rhs) {
      fArray     = rhs.fArray;
      fDirection = rhs.fDirection;
      fCursor    = rhs.fCursor;
      fCurCursor = rhs.fCurCursor;
   }
   return *this;
}
TObject *TObjArrayIter::Next()
{
   
   if (fDirection == kIterForward) {
      for ( ; fCursor < fArray->Capacity() && fArray->fCont[fCursor] == 0;
              fCursor++) { }
      fCurCursor = fCursor;
      if (fCursor < fArray->Capacity()) {
         return fArray->fCont[fCursor++];
      }
   } else {
      for ( ; fCursor >= 0 && fArray->fCont[fCursor] == 0;
              fCursor--) { }
      fCurCursor = fCursor;
      if (fCursor >= 0) {
         return fArray->fCont[fCursor--];
      }
   }
   return 0;
}
void TObjArrayIter::Reset()
{
   
   if (fDirection == kIterForward)
      fCursor = 0;
   else
      fCursor = fArray->Capacity() - 1;
   fCurCursor = fCursor;
}
bool TObjArrayIter::operator!=(const TIterator &aIter) const
{
   
   if (nullptr == (&aIter))
      return (fCurCursor < fArray->Capacity());
   if (aIter.IsA() == TObjArrayIter::Class()) {
      const TObjArrayIter &iter(dynamic_cast<const TObjArrayIter &>(aIter));
      return (fCurCursor != iter.fCurCursor);
   }
   return false; 
}
bool TObjArrayIter::operator!=(const TObjArrayIter &aIter) const
{
   
   if (nullptr == (&aIter))
      return (fCurCursor < fArray->Capacity());
   return (fCurCursor != aIter.fCurCursor);
}
TObject *TObjArrayIter::operator*() const
{
   
   return (((fCurCursor >= 0) && (fCurCursor < fArray->Capacity())) ?
           fArray->fCont[fCurCursor] : nullptr);
}
Last change: Tue May 13 17:22:07 2008
Last generated: 2008-05-13 17:22
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.