ROOT  6.06/09
Reference Guide
TOrdCollection.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Fons Rademakers 13/09/95
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 /** \class TOrdCollection
13 Ordered collection. An ordered collection has TList insertion
14 semantics but is implemented using an array of TObject*'s. It uses
15 less space than a TList (since there is no need for the prev and
16 next pointers), but it is more costly to insert objects (since it
17 has to create a gap by copying object pointers). TOrdCollection
18 is better than TList when objects are only added at the end of the
19 collection since no copying needs to be done.
20 */
21 
22 #include "TOrdCollection.h"
23 #include "TError.h"
24 
25 
27 
28 ////////////////////////////////////////////////////////////////////////////////
29 /// Create an ordered collection.
30 
32 {
33  if (capacity < 0) {
34  Warning("TOrdCollection", "capacity (%d) < 0", capacity);
35  capacity = kDefaultCapacity;
36  } else if (capacity == 0)
37  capacity = kDefaultCapacity;
38  Init(capacity);
39 }
40 
41 ////////////////////////////////////////////////////////////////////////////////
42 /// Delete the collection. Objects are not deleted unless the TOrdCollection
43 /// is the owner (set via SetOwner()).
44 
46 {
47  if (IsOwner())
48  Delete();
49 
51  fCont = 0;
52  fSize = 0;
53 }
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 /// Insert object at position idx in the collection.
57 
59 {
60  Int_t physIdx;
61 
62  if (idx > fSize) idx = fSize;
63 
64  if (fGapSize <= 0)
66 
67  if (idx == fGapStart) {
68  physIdx = fGapStart;
69  fGapStart++;
70  } else {
71  physIdx = PhysIndex(idx);
72  if (physIdx < fGapStart) {
73  MoveGapTo(physIdx);
74  physIdx = fGapStart;
75  fGapStart++;
76  } else {
77  MoveGapTo(physIdx - fGapSize);
78  physIdx = fGapStart + fGapSize - 1;
79  }
80  }
81  R__ASSERT(physIdx >= 0 && physIdx < fCapacity);
82  fCont[physIdx] = obj;
83  fGapSize--;
84  fSize++;
85  Changed();
86 }
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 /// Insert object at beginning of collection.
90 
92 {
93  AddAt(obj, 0);
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// Add object at the end of the collection.
98 
100 {
101  AddAt(obj, fSize);
102 }
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Insert object before object before in the collection.
106 
108 {
109  if (!before)
110  AddFirst(obj);
111  else {
112  Int_t idx = IndexOf(before);
113  if (idx == -1) {
114  Error("AddBefore", "before not found, object not added");
115  return;
116  }
117  if (idx == 0) {
118  AddFirst(obj);
119  return;
120  }
121  AddAt(obj, idx);
122  }
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Insert object after object after in the collection.
127 
129 {
130  if (!after)
131  AddLast(obj);
132  else {
133  Int_t idx = IndexOf(after);
134  if (idx == -1) {
135  Error("AddAfter", "after not found, object not added");
136  return;
137  }
138  AddAt(obj, idx+1);
139  }
140 }
141 
142 ////////////////////////////////////////////////////////////////////////////////
143 /// Return the object after object obj. Returns 0 if obj is last
144 /// in collection.
145 
147 {
148  if (!obj) return 0;
149 
150  Int_t idx = IndexOf(obj);
151  if (idx == -1 || idx == fSize-1) return 0;
152 
153  return At(idx+1);
154 }
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Returns the object at position idx. Returns 0 if idx is out of range.
158 
160 {
161  if (IllegalIndex("At", idx)) return 0;
162  return fCont[PhysIndex(idx)];
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Returns the object before object obj. Returns 0 if obj is first
167 /// in collection.
168 
170 {
171  if (!obj) return 0;
172 
173  Int_t idx = IndexOf(obj);
174  if (idx == -1 || idx == 0) return 0;
175 
176  return At(idx-1);
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// Remove all objects from the collection. Does not delete the objects
181 /// unless the TOrdCollection is the owner (set via SetOwner()).
182 
184 {
185  if (IsOwner())
186  Delete();
187  else {
189  fCont = 0;
190  Init(fCapacity);
191  fSize = 0;
192  }
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Remove all objects from the collection AND delete all heap based objects.
197 
199 {
200  for (Int_t i = 0; i < fSize; i++) {
201  TObject *obj = At(i);
202  if (obj && obj->IsOnHeap())
204  }
206  fCont = 0;
207  Init(fCapacity);
208  fSize = 0;
209 }
210 
211 ////////////////////////////////////////////////////////////////////////////////
212 /// Return the first object in the collection. Returns 0 when collection
213 /// is empty.
214 
216 {
217  return At(0);
218 }
219 
220 ////////////////////////////////////////////////////////////////////////////////
221 /// return address of pointer obj
222 
224 {
225  Int_t index = IndexOf(obj);
226  return &fCont[index];
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Return the last object in the collection. Returns 0 when collection
231 /// is empty.
232 
234 {
235  return At(fSize-1);
236 }
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// Return true when index out of bounds and print error.
240 
241 Bool_t TOrdCollection::IllegalIndex(const char *method, Int_t idx) const
242 {
243  if (idx < 0 || idx >= fSize) {
244  Error(method, "index error (= %d) < 0 or > Size() (= %d)", idx, fSize);
245  return kTRUE;
246  }
247  return kFALSE;
248 }
249 
250 ////////////////////////////////////////////////////////////////////////////////
251 /// Return index of object in collection. Returns -1 when object not found.
252 /// Uses member IsEqual() to find object.
253 
255 {
256  for (Int_t i = 0; i < GetSize(); i++)
257  if (fCont[PhysIndex(i)]->IsEqual(obj))
258  return i;
259 
260  return -1;
261 }
262 
263 ////////////////////////////////////////////////////////////////////////////////
264 /// Initialize ordered collection.
265 
267 {
268  fCapacity = capacity;
269  fCont = (TObject**) TStorage::Alloc(fCapacity*sizeof(TObject*)); //new TObject* [fCapacity];
270  memset(fCont, 0, fCapacity*sizeof(TObject*));
271  fGapStart = 0;
272  fGapSize = capacity;
273  Changed();
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Return an ordered collection iterator.
278 
280 {
281  return new TOrdCollectionIter(this, dir);
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Move gap to new position. Gap needs to be moved when objects are
286 /// inserted not at the end.
287 
289 {
290  Int_t i;
291 
292  R__ASSERT(start + fGapSize - 1 < fCapacity);
293 
294  if (fGapSize <= 0) {
295  fGapStart = start;
296  return;
297  }
298  if (start < fGapStart) {
299  for (i = fGapStart - 1; i >= start; i--)
300  fCont[i + fGapSize] = fCont[i];
301  } else if (start > fGapStart) {
302  Int_t stop = start + fGapSize;
303  for (i = fGapStart + fGapSize; i < stop; i++)
304  fCont[i - fGapSize] = fCont[i];
305  }
306  fGapStart = start;
307  for (i = fGapStart; i < fGapStart + fGapSize; i++)
308  fCont[i] = 0;
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Put object at index idx. Overwrites what was at idx before.
313 
315 {
316  if (IllegalIndex("PutAt", idx)) return;
317 
318  Int_t phx = PhysIndex(idx);
319  R__ASSERT(phx >= 0 && phx < fCapacity);
320  fCont[phx] = obj;
321  Changed();
322 }
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Remove object at index idx.
326 
328 {
329  Int_t physIdx;
330 
331  if (idx == fGapStart - 1 || idx == fGapStart) {
332  if (idx == fGapStart)
333  physIdx = fGapStart + fGapSize; // at right boundary
334  else
335  physIdx = --fGapStart; // at left boundary
336  } else {
337  physIdx = PhysIndex(idx);
338  if (physIdx < fGapStart) {
339  MoveGapTo(physIdx + 1);
340  physIdx = --fGapStart;
341  } else {
342  MoveGapTo(physIdx - fGapSize);
343  physIdx = fGapStart + fGapSize;
344  }
345  }
346  R__ASSERT(physIdx >= 0 && physIdx < fCapacity);
347  TObject *obj = fCont[physIdx];
348  fCont[physIdx] = 0;
349  fGapSize++;
350  fSize--;
351  Changed();
352 
353  if (LowWaterMark()) {
354  Int_t newCapacity = TMath::Max(int(fCapacity / kShrinkFactor), 1);
355  if (fCapacity > newCapacity)
356  SetCapacity(newCapacity);
357  }
358  return obj;
359 }
360 
361 ////////////////////////////////////////////////////////////////////////////////
362 /// Remove object from collection.
363 
365 {
366  if (!obj) return 0;
367 
368  Int_t idx = IndexOf(obj);
369  if (idx == -1) return 0;
370 
371  return RemoveAt(idx);
372 }
373 
374 ////////////////////////////////////////////////////////////////////////////////
375 /// Set/change ordered collection capacity.
376 
378 {
379  R__ASSERT(newCapacity > 0);
380  R__ASSERT(fSize <= newCapacity);
381 
382  if (fCapacity == newCapacity) return;
383 
384  Int_t newGapSize = newCapacity - fSize;
386  fCont = (TObject**) TStorage::ReAlloc(fCont, newCapacity*sizeof(TObject*),
387  fCapacity*sizeof(TObject*));
388  fGapSize = newGapSize;
389  fCapacity = newCapacity;
390 }
391 
392 ////////////////////////////////////////////////////////////////////////////////
393 /// If objects in collection are sortable (i.e. IsSortable() returns true
394 /// for all objects) then sort collection.
395 
397 {
398  if (fSize <= 0 || fSorted) return;
399  if (!At(0)->IsSortable()) {
400  Error("Sort", "objects in collection are not sortable");
401  return;
402  }
403 
405  QSort(fCont, 0, fSize);
406 
407  fSorted = kTRUE;
408 }
409 
410 ////////////////////////////////////////////////////////////////////////////////
411 /// Find object using a binary search. Collection must first have been
412 /// sorted.
413 
415 {
416  Int_t result;
417 
418  if (!obj) return -1;
419 
420  if (!fSorted) {
421  Error("BinarySearch", "collection must first be sorted");
422  return -1;
423  }
424 
426 
427  Int_t base = 0;
428  Int_t last = base + GetSize() - 1;
429  while (last >= base) {
430  Int_t position = (base + last) / 2;
431  TObject *obj2 = fCont[position];
432  if ((obj2 == 0) || (result = obj->Compare(obj2)) == 0)
433  return LogIndex(position);
434  if (result < 0)
435  last = position - 1;
436  else
437  base = position + 1;
438  }
439  return -1;
440 }
441 
442 /** \class TOrdCollectionIter
443 Iterator of ordered collection.
444 */
445 
447 
448 ////////////////////////////////////////////////////////////////////////////////
449 /// Create collection iterator. By default the iteration direction
450 /// is kIterForward. To go backward use kIterBackward.
451 
452 TOrdCollectionIter::TOrdCollectionIter(const TOrdCollection *col, Bool_t dir): fCol(col), fDirection(dir)
453 {
454  Reset();
455 }
456 
457 ////////////////////////////////////////////////////////////////////////////////
458 /// Copy ctor.
459 
461 {
462  fCol = iter.fCol;
463  fDirection = iter.fDirection;
464  fCursor = iter.fCursor;
465  fCurCursor = iter.fCurCursor;
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// Overridden assignment operator.
470 
472 {
473  if (this != &rhs && rhs.IsA() == TOrdCollectionIter::Class()) {
474  const TOrdCollectionIter &rhs1 = (const TOrdCollectionIter &)rhs;
475  fCol = rhs1.fCol;
476  fDirection = rhs1.fDirection;
477  fCursor = rhs1.fCursor;
478  fCurCursor = rhs1.fCurCursor;
479  }
480  return *this;
481 }
482 
483 ////////////////////////////////////////////////////////////////////////////////
484 /// Overloaded assignment operator.
485 
487 {
488  if (this != &rhs) {
489  fCol = rhs.fCol;
490  fDirection = rhs.fDirection;
491  fCursor = rhs.fCursor;
492  fCurCursor = rhs.fCurCursor;
493  }
494  return *this;
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 /// Return next object in collection. Returns 0 when no more objects in
499 /// collection.
500 
502 {
504  if (fDirection == kIterForward) {
505  if (fCursor < fCol->GetSize())
506  return fCol->At(fCursor++);
507  } else {
508  if (fCursor >= 0)
509  return fCol->At(fCursor--);
510  }
511  return 0;
512 }
513 
514 ////////////////////////////////////////////////////////////////////////////////
515 /// Reset collection iterator.
516 
518 {
519  if (fDirection == kIterForward)
520  fCursor = 0;
521  else
522  fCursor = fCol->GetSize() - 1;
523 
525 }
526 
527 ////////////////////////////////////////////////////////////////////////////////
528 /// This operator compares two TIterator objects.
529 
531 {
532  if (aIter.IsA() == TOrdCollectionIter::Class()) {
533  const TOrdCollectionIter &iter(dynamic_cast<const TOrdCollectionIter &>(aIter));
534  return (fCurCursor != iter.fCurCursor);
535  }
536  return false; // for base class we don't implement a comparison
537 }
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 /// This operator compares two TOrdCollectionIter objects.
541 
543 {
544  return (fCurCursor != aIter.fCurCursor);
545 }
546 
547 ////////////////////////////////////////////////////////////////////////////////
548 /// Return current object or nullptr.
549 
551 {
552  return (((fCurCursor >= 0) && (fCurCursor < fCol->GetSize())) ?
553  fCol->At(fCurCursor) : nullptr);
554 }
static void Dealloc(void *ptr)
De-allocate block of memory, that was allocated via TStorage::Alloc().
Definition: TStorage.cxx:164
void Init(Int_t capacity)
Initialize ordered collection.
Bool_t IsOnHeap() const
Definition: TObject.h:140
void Delete(Option_t *option="")
Remove all objects from the collection AND delete all heap based objects.
TObject * Last() const
Return the last object in the collection.
const char Option_t
Definition: RtypesCore.h:62
TObject * Before(const TObject *obj) const
Returns the object before object obj.
void AddLast(TObject *obj)
Add object at the end of the collection.
TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
TObject * After(const TObject *obj) const
Return the object after object obj.
#define R__ASSERT(e)
Definition: TError.h:98
Bool_t IsSortable() const
Definition: TCollection.h:102
TObject * First() const
Return the first object in the collection.
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the collection.
const Bool_t kFALSE
Definition: Rtypes.h:92
TObject ** GetObjectRef(const TObject *obj) const
return address of pointer obj
virtual Bool_t IsEqual(const TObject *obj) const
Default equal comparison (objects are equal if they have the same address in memory).
Definition: TObject.cxx:527
Iterator abstract base class.
Definition: TIterator.h:32
Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Return an ordered collection iterator.
Int_t LogIndex(Int_t idx) const
void Class()
Definition: Class.C:29
virtual void Changed()
TObject * Next()
Return next object in collection.
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:118
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
void PutAt(TObject *obj, Int_t idx)
Put object at index idx. Overwrites what was at idx before.
const Bool_t kIterForward
Definition: TCollection.h:43
void Reset()
Reset collection iterator.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Int_t PhysIndex(Int_t idx) const
~TOrdCollection()
Delete the collection.
void SetCapacity(Int_t newCapacity)
Set/change ordered collection capacity.
TObject ** fCont
Bool_t IsOwner() const
Definition: TCollection.h:101
ClassImp(TOrdCollection) TOrdCollection
Create an ordered collection.
Int_t fSize
Definition: TCollection.h:63
TObject * RemoveAt(Int_t idx)
Remove object at index idx.
void AddFirst(TObject *obj)
Insert object at beginning of collection.
void Reset(Detail::TBranchProxy *x)
void Warning(const char *location, const char *msgfmt,...)
static void QSort(TObject **a, Int_t first, Int_t last)
Sort array of TObject pointers using a quicksort algorithm.
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
TObject * Remove(TObject *obj)
Remove object from collection.
Bool_t LowWaterMark() const
static void * Alloc(size_t size)
Allocate a block of memory, that later can be resized using TStorage::ReAlloc().
Definition: TStorage.cxx:146
static void GarbageCollect(TObject *obj)
Add to the list of things to be cleaned up.
void MoveGapTo(Int_t newGapStart)
Move gap to new position.
void Sort()
If objects in collection are sortable (i.e.
virtual Int_t GetSize() const
Definition: TCollection.h:95
Bool_t IllegalIndex(const char *method, Int_t idx) const
Return true when index out of bounds and print error.
TObject * operator*() const
Return current object or nullptr.
Int_t BinarySearch(TObject *obj)
Find object using a binary search.
Mother of all ROOT objects.
Definition: TObject.h:58
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:177
const TOrdCollection * fCol
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
void Clear(Option_t *option="")
Remove all objects from the collection.
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:218
Iterator of ordered collection.
void AddAfter(const TObject *after, TObject *obj)
Insert object after object after in the collection.
double result[121]
void AddAt(TObject *obj, Int_t idx)
Insert object at position idx in the collection.
const Bool_t kTRUE
Definition: Rtypes.h:91
Ordered collection.
TObject * obj
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
friend class TOrdCollectionIter