ROOT logo
// @(#)root/cont:$Id: TSeqCollection.cxx 28588 2009-05-12 21:43:28Z pcanal $
// Author: Fons Rademakers   04/08/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSeqCollection                                                       //
//                                                                      //
// Sequenceable collection abstract base class. TSeqCollection's have   //
// an ordering relation, i.e. there is a first and last element.        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TSeqCollection.h"
#include "TCollection.h"
#include "TVirtualMutex.h"
#include "TClass.h"
#include "TMethodCall.h"

ClassImp(TSeqCollection)

//______________________________________________________________________________
Int_t TSeqCollection::IndexOf(const TObject *obj) const
{
   // Return index of object in collection. Returns -1 when object not found.
   // Uses member IsEqual() to find object.

   Int_t   idx = 0;
   TIter   next(this);
   TObject *ob;

   while ((ob = next())) {
      if (ob->IsEqual(obj)) return idx;
      idx++;
   }
   return -1;
}

//______________________________________________________________________________
Int_t TSeqCollection::ObjCompare(TObject *a, TObject *b)
{
   // Compare to objects in the collection. Use member Compare() of object a.

   if (a == 0 && b == 0) return 0;
   if (a == 0) return 1;
   if (b == 0) return -1;
   return a->Compare(b);
}

//______________________________________________________________________________
void TSeqCollection::QSort(TObject **a, Int_t first, Int_t last)
{
   // Sort array of TObject pointers using a quicksort algorithm.
   // Uses ObjCompare() to compare objects.

   R__LOCKGUARD2(gCollectionMutex);

   static TObject *tmp;
   static int i;           // "static" to save stack space
   int j;

   while (last - first > 1) {
      i = first;
      j = last;
      for (;;) {
         while (++i < last && ObjCompare(a[i], a[first]) < 0)
            ;
         while (--j > first && ObjCompare(a[j], a[first]) > 0)
            ;
         if (i >= j)
            break;

         tmp  = a[i];
         a[i] = a[j];
         a[j] = tmp;
      }
      if (j == first) {
         ++first;
         continue;
      }
      tmp = a[first];
      a[first] = a[j];
      a[j] = tmp;
      if (j - first < last - (j + 1)) {
         QSort(a, first, j);
         first = j + 1;   // QSort(j + 1, last);
      } else {
         QSort(a, j + 1, last);
         last = j;        // QSort(first, j);
      }
   }
}

//______________________________________________________________________________
void TSeqCollection::QSort(TObject **a, TObject **b, Int_t first, Int_t last)
{
   // Sort array a of TObject pointers using a quicksort algorithm.
   // Array b will be sorted just like a (a determines the sort).
   // Uses ObjCompare() to compare objects.

   R__LOCKGUARD2(gCollectionMutex);
   static TObject *tmp1, *tmp2;
   static int i;           // "static" to save stack space
   int j;

   while (last - first > 1) {
      i = first;
      j = last;
      for (;;) {
         while (++i < last && ObjCompare(a[i], a[first]) < 0)
            ;
         while (--j > first && ObjCompare(a[j], a[first]) > 0)
            ;
         if (i >= j)
            break;

         tmp1 = a[i]; tmp2 = b[i];
         a[i] = a[j]; b[i] = b[j];
         a[j] = tmp1; b[j] = tmp2;
      }
      if (j == first) {
         ++first;
         continue;
      }
      tmp1 = a[first]; tmp2 = b[first];
      a[first] = a[j]; b[first] = b[j];
      a[j] = tmp1;     b[j] = tmp2;
      if (j - first < last - (j + 1)) {
         QSort(a, b, first, j);
         first = j + 1;   // QSort(j + 1, last);
      } else {
         QSort(a, b, j + 1, last);
         last = j;        // QSort(first, j);
      }
   }
}

//______________________________________________________________________________
Long64_t TSeqCollection::Merge(TCollection *list)
{
   // Merge this collection with all collections coming in the input list. The
   // input list must contain other collections of objects compatible with the
   // ones in this collection and ordered in the same manner. For example, if this
   // collection contains a TH1 object and a tree, all collections in the input
   // list have to contain a histogram and a tree. In case the list contains
   // collections, the objects in the input lists must also be collections with
   // the same structure and number of objects.
   //
   // Example
   // =========
   //   this                          list
   // ____________                  ---------------------|
   // | A (TH1F) |  __________      | L1 (TSeqCollection)|- [A1, B1(C1,D1,E1)]
   // | B (TList)|-| C (TTree)|     | L1 (TSeqCollection)|- [A2, B2(C2,D2,E2)]
   // |__________| | D (TH1F) |     | ...                |- [...]
   //              | E (TH1F) |     |____________________|
   //              |__________|

   Long64_t nmerged = 0;
   if (IsEmpty() || !list) {
      Warning("Merge", "list is empty - nothing to merge");
      return 0;
   }
   if (list->IsEmpty()) {
      Warning("Merge", "input list is empty - nothing to merge with");
      return 0;
   }
   TIter nextobject(this);
   TIter nextlist(list);
   TObject *object;
   TObject *objtomerge;
   TObject *collcrt;
   TSeqCollection *templist;
   TMethodCall callEnv;
   Int_t indobj = 0;
   while ((object = nextobject())) {   // loop objects in this collection
      // If current object is not mergeable just skip it
      if (!object->IsA()) {
         indobj++;  // current object non-mergeable, go to next object
         continue;
      }
      callEnv.InitWithPrototype(object->IsA(), "Merge", "TCollection*");
      if (!callEnv.IsValid()) {
         indobj++;  // no Merge() interface, go to next object
         continue;
      }
      // Current object mergeable - get corresponding objects in input lists
      templist = (TSeqCollection*)IsA()->New();
      nextlist.Reset();
      while ((collcrt = nextlist())) {      // loop input lists
         if (!collcrt->InheritsFrom(TSeqCollection::Class())) {
            Error("Merge", "some objects in the input list are not collections - merging aborted");
            delete templist;
            return 0;
         }
         // The next object to be merged with is a collection
         // the iterator skips the 'holes' the collections, we also need to do so.
         objtomerge = ((TSeqCollection*)collcrt)->At(indobj);
         while (objtomerge == 0
                && indobj < ((TSeqCollection*)collcrt)->LastIndex() 
               ) {
            ++indobj;
            objtomerge = ((TSeqCollection*)collcrt)->At(indobj);
         }
         if (object->IsA() != objtomerge->IsA()) {
            Error("Merge", "object of type %s at index %d not matching object of type %s in input list",
                  object->ClassName(), indobj, objtomerge->ClassName());
            delete templist;
            return 0;
         }
         // Add object at index indobj in the temporary list
         templist->Add(objtomerge);
         nmerged++;
      }
      // Merge current object with objects in the temporary list
      callEnv.SetParam((Long_t) templist);
      callEnv.Execute(object);
      delete templist;
      indobj++;
   }
   return nmerged;
}
 TSeqCollection.cxx:1
 TSeqCollection.cxx:2
 TSeqCollection.cxx:3
 TSeqCollection.cxx:4
 TSeqCollection.cxx:5
 TSeqCollection.cxx:6
 TSeqCollection.cxx:7
 TSeqCollection.cxx:8
 TSeqCollection.cxx:9
 TSeqCollection.cxx:10
 TSeqCollection.cxx:11
 TSeqCollection.cxx:12
 TSeqCollection.cxx:13
 TSeqCollection.cxx:14
 TSeqCollection.cxx:15
 TSeqCollection.cxx:16
 TSeqCollection.cxx:17
 TSeqCollection.cxx:18
 TSeqCollection.cxx:19
 TSeqCollection.cxx:20
 TSeqCollection.cxx:21
 TSeqCollection.cxx:22
 TSeqCollection.cxx:23
 TSeqCollection.cxx:24
 TSeqCollection.cxx:25
 TSeqCollection.cxx:26
 TSeqCollection.cxx:27
 TSeqCollection.cxx:28
 TSeqCollection.cxx:29
 TSeqCollection.cxx:30
 TSeqCollection.cxx:31
 TSeqCollection.cxx:32
 TSeqCollection.cxx:33
 TSeqCollection.cxx:34
 TSeqCollection.cxx:35
 TSeqCollection.cxx:36
 TSeqCollection.cxx:37
 TSeqCollection.cxx:38
 TSeqCollection.cxx:39
 TSeqCollection.cxx:40
 TSeqCollection.cxx:41
 TSeqCollection.cxx:42
 TSeqCollection.cxx:43
 TSeqCollection.cxx:44
 TSeqCollection.cxx:45
 TSeqCollection.cxx:46
 TSeqCollection.cxx:47
 TSeqCollection.cxx:48
 TSeqCollection.cxx:49
 TSeqCollection.cxx:50
 TSeqCollection.cxx:51
 TSeqCollection.cxx:52
 TSeqCollection.cxx:53
 TSeqCollection.cxx:54
 TSeqCollection.cxx:55
 TSeqCollection.cxx:56
 TSeqCollection.cxx:57
 TSeqCollection.cxx:58
 TSeqCollection.cxx:59
 TSeqCollection.cxx:60
 TSeqCollection.cxx:61
 TSeqCollection.cxx:62
 TSeqCollection.cxx:63
 TSeqCollection.cxx:64
 TSeqCollection.cxx:65
 TSeqCollection.cxx:66
 TSeqCollection.cxx:67
 TSeqCollection.cxx:68
 TSeqCollection.cxx:69
 TSeqCollection.cxx:70
 TSeqCollection.cxx:71
 TSeqCollection.cxx:72
 TSeqCollection.cxx:73
 TSeqCollection.cxx:74
 TSeqCollection.cxx:75
 TSeqCollection.cxx:76
 TSeqCollection.cxx:77
 TSeqCollection.cxx:78
 TSeqCollection.cxx:79
 TSeqCollection.cxx:80
 TSeqCollection.cxx:81
 TSeqCollection.cxx:82
 TSeqCollection.cxx:83
 TSeqCollection.cxx:84
 TSeqCollection.cxx:85
 TSeqCollection.cxx:86
 TSeqCollection.cxx:87
 TSeqCollection.cxx:88
 TSeqCollection.cxx:89
 TSeqCollection.cxx:90
 TSeqCollection.cxx:91
 TSeqCollection.cxx:92
 TSeqCollection.cxx:93
 TSeqCollection.cxx:94
 TSeqCollection.cxx:95
 TSeqCollection.cxx:96
 TSeqCollection.cxx:97
 TSeqCollection.cxx:98
 TSeqCollection.cxx:99
 TSeqCollection.cxx:100
 TSeqCollection.cxx:101
 TSeqCollection.cxx:102
 TSeqCollection.cxx:103
 TSeqCollection.cxx:104
 TSeqCollection.cxx:105
 TSeqCollection.cxx:106
 TSeqCollection.cxx:107
 TSeqCollection.cxx:108
 TSeqCollection.cxx:109
 TSeqCollection.cxx:110
 TSeqCollection.cxx:111
 TSeqCollection.cxx:112
 TSeqCollection.cxx:113
 TSeqCollection.cxx:114
 TSeqCollection.cxx:115
 TSeqCollection.cxx:116
 TSeqCollection.cxx:117
 TSeqCollection.cxx:118
 TSeqCollection.cxx:119
 TSeqCollection.cxx:120
 TSeqCollection.cxx:121
 TSeqCollection.cxx:122
 TSeqCollection.cxx:123
 TSeqCollection.cxx:124
 TSeqCollection.cxx:125
 TSeqCollection.cxx:126
 TSeqCollection.cxx:127
 TSeqCollection.cxx:128
 TSeqCollection.cxx:129
 TSeqCollection.cxx:130
 TSeqCollection.cxx:131
 TSeqCollection.cxx:132
 TSeqCollection.cxx:133
 TSeqCollection.cxx:134
 TSeqCollection.cxx:135
 TSeqCollection.cxx:136
 TSeqCollection.cxx:137
 TSeqCollection.cxx:138
 TSeqCollection.cxx:139
 TSeqCollection.cxx:140
 TSeqCollection.cxx:141
 TSeqCollection.cxx:142
 TSeqCollection.cxx:143
 TSeqCollection.cxx:144
 TSeqCollection.cxx:145
 TSeqCollection.cxx:146
 TSeqCollection.cxx:147
 TSeqCollection.cxx:148
 TSeqCollection.cxx:149
 TSeqCollection.cxx:150
 TSeqCollection.cxx:151
 TSeqCollection.cxx:152
 TSeqCollection.cxx:153
 TSeqCollection.cxx:154
 TSeqCollection.cxx:155
 TSeqCollection.cxx:156
 TSeqCollection.cxx:157
 TSeqCollection.cxx:158
 TSeqCollection.cxx:159
 TSeqCollection.cxx:160
 TSeqCollection.cxx:161
 TSeqCollection.cxx:162
 TSeqCollection.cxx:163
 TSeqCollection.cxx:164
 TSeqCollection.cxx:165
 TSeqCollection.cxx:166
 TSeqCollection.cxx:167
 TSeqCollection.cxx:168
 TSeqCollection.cxx:169
 TSeqCollection.cxx:170
 TSeqCollection.cxx:171
 TSeqCollection.cxx:172
 TSeqCollection.cxx:173
 TSeqCollection.cxx:174
 TSeqCollection.cxx:175
 TSeqCollection.cxx:176
 TSeqCollection.cxx:177
 TSeqCollection.cxx:178
 TSeqCollection.cxx:179
 TSeqCollection.cxx:180
 TSeqCollection.cxx:181
 TSeqCollection.cxx:182
 TSeqCollection.cxx:183
 TSeqCollection.cxx:184
 TSeqCollection.cxx:185
 TSeqCollection.cxx:186
 TSeqCollection.cxx:187
 TSeqCollection.cxx:188
 TSeqCollection.cxx:189
 TSeqCollection.cxx:190
 TSeqCollection.cxx:191
 TSeqCollection.cxx:192
 TSeqCollection.cxx:193
 TSeqCollection.cxx:194
 TSeqCollection.cxx:195
 TSeqCollection.cxx:196
 TSeqCollection.cxx:197
 TSeqCollection.cxx:198
 TSeqCollection.cxx:199
 TSeqCollection.cxx:200
 TSeqCollection.cxx:201
 TSeqCollection.cxx:202
 TSeqCollection.cxx:203
 TSeqCollection.cxx:204
 TSeqCollection.cxx:205
 TSeqCollection.cxx:206
 TSeqCollection.cxx:207
 TSeqCollection.cxx:208
 TSeqCollection.cxx:209
 TSeqCollection.cxx:210
 TSeqCollection.cxx:211
 TSeqCollection.cxx:212
 TSeqCollection.cxx:213
 TSeqCollection.cxx:214
 TSeqCollection.cxx:215
 TSeqCollection.cxx:216
 TSeqCollection.cxx:217
 TSeqCollection.cxx:218
 TSeqCollection.cxx:219
 TSeqCollection.cxx:220
 TSeqCollection.cxx:221
 TSeqCollection.cxx:222
 TSeqCollection.cxx:223
 TSeqCollection.cxx:224
 TSeqCollection.cxx:225
 TSeqCollection.cxx:226
 TSeqCollection.cxx:227
 TSeqCollection.cxx:228
 TSeqCollection.cxx:229