#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
{
Int_t idx = 0;
TIter next(this);
TObject *ob;
while ((ob = next())) {
if (ob->IsEqual(obj)) return idx;
idx++;
}
return -1;
}
Int_t TSeqCollection::GetLast() const
{
TObject *tmp = Last();
return tmp ? IndexOf(tmp) : -1;
}
Int_t TSeqCollection::ObjCompare(TObject *a, TObject *b)
{
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)
{
R__LOCKGUARD2(gCollectionMutex);
static TObject *tmp;
static int i;
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;
} else {
QSort(a, j + 1, last);
last = j;
}
}
}
void TSeqCollection::QSort(TObject **a, Int_t nBs, TObject ***b, Int_t first, Int_t last)
{
R__LOCKGUARD2(gCollectionMutex);
static TObject *tmp1, **tmp2;
static int i;
int j,k;
static int depth = 0;
if (depth == 0 && nBs > 0) tmp2 = new TObject*[nBs];
depth++;
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]; for(k=0;k<nBs;k++) tmp2[k] = b[k][i];
a[i] = a[j]; for(k=0;k<nBs;k++) b[k][i] = b[k][j];
a[j] = tmp1; for(k=0;k<nBs;k++) b[k][j] = tmp2[k];
}
if (j == first) {
++first;
continue;
}
tmp1 = a[first]; for(k=0;k<nBs;k++) tmp2[k] = b[k][first];
a[first] = a[j]; for(k=0;k<nBs;k++) b[k][first] = b[k][j];
a[j] = tmp1; for(k=0;k<nBs;k++) b[k][j] = tmp2[k];
if (j - first < last - (j + 1)) {
QSort(a, nBs, b, first, j);
first = j + 1;
} else {
QSort(a, nBs, b, j + 1, last);
last = j;
}
}
depth--;
if (depth == 0 && nBs > 0) delete [] tmp2;
}
Long64_t TSeqCollection::Merge(TCollection *list)
{
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 = 0;
TMethodCall callEnv;
Int_t indobj = 0;
TSeqCollection *notmergeable = 0;
Bool_t mergeable = kTRUE;
while ((object = nextobject())) {
mergeable = kTRUE;
if (!object->IsA()) {
mergeable = kFALSE;
} else {
callEnv.InitWithPrototype(object->IsA(), "Merge", "TCollection*");
if (!callEnv.IsValid()) mergeable = kFALSE;
}
if (mergeable) {
templist = (TSeqCollection*)IsA()->New();
} else {
templist = 0;
}
nextlist.Reset();
Int_t indcoll = 0;
while ((collcrt = nextlist())) {
if (!collcrt->InheritsFrom(TSeqCollection::Class())) {
Error("Merge", "some objects in the input list are not collections - merging aborted");
SafeDelete(templist);
return 0;
}
objtomerge = ((TSeqCollection*)collcrt)->At(indobj);
if (!objtomerge) {
Warning("Merge", "object of type %s (position %d in list) not found in list %d. Continuing...",
object->ClassName(), indobj, indcoll);
continue;
}
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());
SafeDelete(templist);
return 0;
}
if (mergeable) {
templist->Add(objtomerge);
nmerged++;
} else {
if (!notmergeable && IsA())
notmergeable = (TSeqCollection*)IsA()->New();
if (notmergeable)
notmergeable->Add(objtomerge);
else
Warning("Merge", "temp list for non mergeable objects not created!");
}
}
if (mergeable) {
callEnv.SetParam((Long_t) templist);
callEnv.Execute(object);
SafeDelete(templist);
}
indobj++;
}
if (notmergeable && notmergeable->GetSize() > 0) {
TIter nxnm(notmergeable);
TObject *onm = 0;
while ((onm = nxnm())) { Add(onm->Clone()); }
SafeDelete(notmergeable);
}
return nmerged;
}