/*
<img src=gif/tordcollection.gif>
*/
//End_Html
#include "TOrdCollection.h"
#include "TError.h"
ClassImp(TOrdCollection)
TOrdCollection::TOrdCollection(Int_t capacity)
{
   
   if (capacity < 0) {
      Warning("TOrdCollection", "capacity (%d) < 0", capacity);
      capacity = kDefaultCapacity;
   } else if (capacity == 0)
      capacity = kDefaultCapacity;
   Init(capacity);
}
TOrdCollection::~TOrdCollection()
{
   
   
   if (IsOwner())
      Delete();
   TStorage::Dealloc(fCont);
   fCont = 0;
   fSize = 0;
}
void TOrdCollection::AddAt(TObject *obj, Int_t idx)
{
   
   Int_t physIdx;
   if (idx > fSize) idx = fSize;
   if (fGapSize <= 0)
      SetCapacity(GrowBy(TMath::Max(fCapacity, (int)kMinExpand)));
   if (idx == fGapStart) {
      physIdx = fGapStart;
      fGapStart++;
   } else {
      physIdx = PhysIndex(idx);
      if (physIdx < fGapStart) {
         MoveGapTo(physIdx);
         physIdx = fGapStart;
         fGapStart++;
      } else {
         MoveGapTo(physIdx - fGapSize);
         physIdx = fGapStart + fGapSize - 1;
      }
   }
   R__ASSERT(physIdx >= 0 && physIdx < fCapacity);
   fCont[physIdx] = obj;
   fGapSize--;
   fSize++;
   Changed();
}
void TOrdCollection::AddFirst(TObject *obj)
{
   
   AddAt(obj, 0);
}
void TOrdCollection::AddLast(TObject *obj)
{
   
   AddAt(obj, fSize);
}
void TOrdCollection::AddBefore(const TObject *before, TObject *obj)
{
   
   if (!before)
      AddFirst(obj);
   else {
      Int_t idx = IndexOf(before);
      if (idx == -1) {
         Error("AddBefore", "before not found, object not added");
         return;
      }
      if (idx == 0) {
         AddFirst(obj);
         return;
      }
      AddAt(obj, idx);
   }
}
void TOrdCollection::AddAfter(const TObject *after, TObject *obj)
{
   
   if (!after)
      AddLast(obj);
   else {
      Int_t idx = IndexOf(after);
      if (idx == -1) {
         Error("AddAfter", "after not found, object not added");
         return;
      }
      AddAt(obj, idx+1);
   }
}
TObject *TOrdCollection::After(const TObject *obj) const
{
   
   
   if (!obj) return 0;
   Int_t idx = IndexOf(obj);
   if (idx == -1 || idx == fSize-1) return 0;
   return At(idx+1);
}
TObject *TOrdCollection::At(Int_t idx) const
{
   
   if (IllegalIndex("At", idx)) return 0;
   return fCont[PhysIndex(idx)];
}
TObject *TOrdCollection::Before(const TObject *obj) const
{
   
   
   if (!obj) return 0;
   Int_t idx = IndexOf(obj);
   if (idx == -1 || idx == 0) return 0;
   return At(idx-1);
}
void TOrdCollection::Clear(Option_t *)
{
   
   
   if (IsOwner())
      Delete();
   else {
      TStorage::Dealloc(fCont);
      fCont = 0;
      Init(fCapacity);
      fSize = 0;
   }
}
void TOrdCollection::Delete(Option_t *)
{
   
   for (Int_t i = 0; i < fSize; i++) {
      TObject *obj = At(i);
      if (obj && obj->IsOnHeap())
         TCollection::GarbageCollect(obj);
   }
   TStorage::Dealloc(fCont);
   fCont = 0;
   Init(fCapacity);
   fSize = 0;
}
TObject *TOrdCollection::First() const
{
   
   
   return At(0);
}
TObject **TOrdCollection::GetObjectRef(const TObject *obj) const
{
   
   Int_t index = IndexOf(obj);
   return &fCont[index];
}
TObject *TOrdCollection::Last() const
{
   
   
   return At(fSize-1);
}
Bool_t TOrdCollection::IllegalIndex(const char *method, Int_t idx) const
{
   
   if (idx < 0 || idx >= fSize) {
      Error(method, "index error (= %d) < 0 or > Size() (= %d)", idx, fSize);
      return kTRUE;
   }
   return kFALSE;
}
Int_t TOrdCollection::IndexOf(const TObject *obj) const
{
   
   
   for (Int_t i = 0; i < GetSize(); i++)
      if (fCont[PhysIndex(i)]->IsEqual(obj))
         return i;
   return -1;
}
void TOrdCollection::Init(Int_t capacity)
{
   
   fCapacity = capacity;
   fCont = (TObject**) TStorage::Alloc(fCapacity*sizeof(TObject*)); 
   memset(fCont, 0, fCapacity*sizeof(TObject*));
   fGapStart = 0;
   fGapSize  = capacity;
   Changed();
}
TIterator *TOrdCollection::MakeIterator(Bool_t dir) const
{
   
   return new TOrdCollectionIter(this, dir);
}
void TOrdCollection::MoveGapTo(Int_t start)
{
   
   
   Int_t i;
   R__ASSERT(start + fGapSize - 1 < fCapacity);
   if (fGapSize <= 0) {
      fGapStart = start;
      return;
   }
   if (start < fGapStart) {
      for (i = fGapStart - 1; i >= start; i--)
         fCont[i + fGapSize] = fCont[i];
   } else if (start > fGapStart) {
      Int_t stop = start + fGapSize;
      for (i = fGapStart + fGapSize; i < stop; i++)
         fCont[i - fGapSize] = fCont[i];
   }
   fGapStart = start;
   for (i = fGapStart; i < fGapStart + fGapSize; i++)
      fCont[i] = 0;
}
void TOrdCollection::PutAt(TObject *obj, Int_t idx)
{
   
   if (IllegalIndex("PutAt", idx)) return;
   Int_t phx = PhysIndex(idx);
   R__ASSERT(phx >= 0 && phx < fCapacity);
   fCont[phx] = obj;
   Changed();
}
TObject *TOrdCollection::RemoveAt(Int_t idx)
{
   
   Int_t physIdx;
   if (idx == fGapStart - 1 || idx == fGapStart) {
      if (idx == fGapStart)
         physIdx = fGapStart + fGapSize;        
      else
         physIdx = --fGapStart;                 
   } else {
      physIdx = PhysIndex(idx);
      if (physIdx < fGapStart) {
         MoveGapTo(physIdx + 1);
         physIdx = --fGapStart;
      } else {
         MoveGapTo(physIdx - fGapSize);
         physIdx = fGapStart + fGapSize;
      }
   }
   R__ASSERT(physIdx >= 0 && physIdx < fCapacity);
   TObject *obj = fCont[physIdx];
   fCont[physIdx] = 0;
   fGapSize++;
   fSize--;
   Changed();
   if (LowWaterMark()) {
      Int_t newCapacity = TMath::Max(int(fCapacity / kShrinkFactor), 1);
      if (fCapacity > newCapacity)
         SetCapacity(newCapacity);
   }
   return obj;
}
TObject *TOrdCollection::Remove(TObject *obj)
{
   
   if (!obj) return 0;
   Int_t idx = IndexOf(obj);
   if (idx == -1) return 0;
   return RemoveAt(idx);
}
void TOrdCollection::SetCapacity(Int_t newCapacity)
{
   
   R__ASSERT(newCapacity > 0);
   R__ASSERT(fSize <= newCapacity);
   if (fCapacity == newCapacity) return;
   Int_t newGapSize = newCapacity - fSize;
   MoveGapTo(fCapacity - fGapSize);
   fCont = (TObject**) TStorage::ReAlloc(fCont, newCapacity*sizeof(TObject*),
                                         fCapacity*sizeof(TObject*));
   fGapSize  = newGapSize;
   fCapacity = newCapacity;
}
void TOrdCollection::Sort()
{
   
   
   if (fSize <= 0 || fSorted) return;
   if (!At(0)->IsSortable()) {
      Error("Sort", "objects in collection are not sortable");
      return;
   }
   MoveGapTo(fCapacity - fGapSize);
   QSort(fCont, 0, fSize);
   fSorted = kTRUE;
}
Int_t TOrdCollection::BinarySearch(TObject *obj)
{
   
   
   Int_t result;
   if (!obj) return -1;
   if (!fSorted) {
      Error("BinarySearch", "collection must first be sorted");
      return -1;
   }
   MoveGapTo(fCapacity - fGapSize);
   Int_t base = 0;
   Int_t last = base + GetSize() - 1;
   while (last >= base) {
      Int_t position = (base + last) / 2;
      TObject *obj2 = fCont[position];
      if ((obj2 == 0) || (result = obj->Compare(obj2)) == 0)
         return LogIndex(position);
      if (result < 0)
         last = position - 1;
      else
         base = position + 1;
   }
   return -1;
}
ClassImp(TOrdCollectionIter)
TOrdCollectionIter::TOrdCollectionIter(const TOrdCollection *col, Bool_t dir)
{
   
   
   fCol = col;
   fDirection = dir;
   Reset();
}
TOrdCollectionIter::TOrdCollectionIter(const TOrdCollectionIter &iter) : TIterator(iter)
{
   
   fCol       = iter.fCol;
   fDirection = iter.fDirection;
   fCursor    = iter.fCursor;
}
TIterator &TOrdCollectionIter::operator=(const TIterator &rhs)
{
   
   if (this != &rhs && rhs.IsA() == TOrdCollectionIter::Class()) {
      const TOrdCollectionIter &rhs1 = (const TOrdCollectionIter &)rhs;
      fCol       = rhs1.fCol;
      fDirection = rhs1.fDirection;
      fCursor    = rhs1.fCursor;
   }
   return *this;
}
TOrdCollectionIter &TOrdCollectionIter::operator=(const TOrdCollectionIter &rhs)
{
   
   if (this != &rhs) {
      fCol       = rhs.fCol;
      fDirection = rhs.fDirection;
      fCursor    = rhs.fCursor;
   }
   return *this;
}
TObject *TOrdCollectionIter::Next()
{
   
   
   if (fDirection == kIterForward) {
      if (fCursor < fCol->GetSize())
         return fCol->At(fCursor++);
   } else {
      if (fCursor >= 0)
         return fCol->At(fCursor--);
   }
   return 0;
}
void TOrdCollectionIter::Reset()
{
   
   if (fDirection == kIterForward)
      fCursor = 0;
   else
      fCursor = fCol->GetSize() - 1;
}
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.