/// \file /// \ingroup tutorial_ProcFileElements /// /// Class to hold information about the processed elements of a file /// /// \macro_code /// /// \author Gerardo Ganis (gerardo.ganis@cern.ch) #include "ProcFileElements.h" #include "TCollection.h" //_______________________________________________________________________ Int_t ProcFileElements::ProcFileElement::Compare(const TObject *o) const { // Compare this element with 'e'. // Return // -1 this should come first // 0 same // 1 e should come first const ProcFileElements::ProcFileElement *e = dynamic_cast(o); if (!e) return -1; if (fFirst == e->fFirst) { // They start at the same point return 0; } else if (fFirst < e->fFirst) { // This starts first return -1; } else { // e starts first return 1; } } //_______________________________________________________________________ Int_t ProcFileElements::ProcFileElement::Overlapping(ProcFileElement *e) { // Check overlapping status of this element with 'e'. // Return // -1 not overlapping // 0 adjacent // 1 overlapping if (!e) return -1; if (fFirst == 0 && fLast == -1) { // We cover the full range, so we overlap return 1; } if (fFirst < e->fFirst) { if (fLast >= 0) { if (fLast < e->fFirst - 1) { // Disjoint return -1; } else { // We somehow overlap if (fLast == e->fFirst - 1) { // Just adjacent return 0; } else { // Real overlap return 1; } } } else { // Always overlapping return 1; } } else if (fFirst == e->fFirst) { // Overlapping or adjacent if (fFirst == fLast || e->fFirst == e->fLast) return 0; return 1; } else { // The other way around if (e->fLast >= 0) { if (e->fLast < fFirst - 1) { // Disjoint return -1; } else { // We somehow overlap if (e->fLast == fFirst - 1) { // Just adjacent return 0; } else { // Real overlap return 1; } } } else { // Always overlapping return 1; } } // Should never be here Warning("Overlapping", "should never be here!"); return -1; } //_______________________________________________________________________ Int_t ProcFileElements::ProcFileElement::MergeElement(ProcFileElement *e) { // Merge this element with element 'e'. // Return -1 if it cannot be done, i.e. thei are disjoint; 0 otherwise // Check if it can be done if (Overlapping(e) < 0) return -1; // Ok, we can merge: set the lower bound if (e->fFirst < fFirst) fFirst = e->fFirst; // Set the upper bound if (fLast == -1 || e->fLast == -1) { fLast = -1; } else { if (fLast < e->fLast) fLast = e->fLast; } // Done return 0; } //_______________________________________________________________________ void ProcFileElements::ProcFileElement::Print(Option_t *) const { // Print range of this element Printf("\tfirst: %lld\t last: %lld", fFirst, fLast); } //_______________________________________________________________________ Int_t ProcFileElements::Add(Long64_t fst, Long64_t lst) { // Add a new element to the list // Return 1 if a new element has been added, 0 if it has been merged // with an existing one, -1 in case of error if (!fElements) fElements = new TSortedList; if (!fElements) { Error("Add", "could not create internal list!"); return -1; } // Create (temporary element) ProcFileElements::ProcFileElement *ne = new ProcFileElements::ProcFileElement(fst, lst); // Check if if it is adjacent or overlapping with an existing one TIter nxe(fElements); ProcFileElements::ProcFileElement *e = 0; while ((e = (ProcFileElements::ProcFileElement *)nxe())) { if (e->MergeElement(ne) == 0) break; } Int_t rc = 0; // Remove and re-add the merged element to sort correctly its possibly new position if (e) { fElements->Remove(e); fElements->Add(e); SafeDelete(ne); } else { // Add the new element fElements->Add(ne); rc = 1; } // Make sure that all what can be merged is merged (because of the order, some elements // which could be merged are not merged, making the determination of fFirst and fLast below // to give incorrect values) ProcFileElements::ProcFileElement *ep = 0, *en = 0; TObjLink *olp = fElements->FirstLink(), *oln = 0; while (olp && (ep = (ProcFileElements::ProcFileElement *) olp->GetObject())) { oln = olp->Next(); while (oln) { if ((en = (ProcFileElements::ProcFileElement *) oln->GetObject())) { if (ep->MergeElement(en) == 0) { fElements->Remove(en); delete en; } } oln = oln->Next(); } olp = olp->Next(); } // New overall ranges if ((e = (ProcFileElements::ProcFileElement *) fElements->First())) fFirst = e->fFirst; if ((e = (ProcFileElements::ProcFileElement *) fElements->Last())) fLast = e->fLast; // Done return rc; } //_______________________________________________________________________ void ProcFileElements::Print(Option_t *) const { // Print info about this processed file Printf("--- ProcFileElements ----------------------------------------"); Printf(" File: %s", fName.Data()); Printf(" # proc elements: %d", fElements ? fElements->GetSize() : 0); TIter nxe(fElements); ProcFileElements::ProcFileElement *e = 0; while ((e = (ProcFileElements::ProcFileElement *)nxe())) { e->Print(); } Printf(" Raw overall range: [%lld, %lld]", fFirst, fLast); Printf("-------------------------------------------------------------"); } //_______________________________________________________________________ Int_t ProcFileElements::Merge(TCollection *li) { // Merge this object with those in the list // Return number of elements added if (!li) return -1; if (li->GetSize() <= 0) return 0; Int_t nadd = 0; TIter nxo(li); ProcFileElements *pfe = 0; while ((pfe = (ProcFileElements *) nxo())) { if (strcmp(GetName(), pfe->GetName())) Warning("Merge", "merging objects of different name! ('%s' != '%s')", GetName(), pfe->GetName()); TIter nxe(pfe->GetListOfElements()); ProcFileElements::ProcFileElement *e = 0; while ((e = (ProcFileElements::ProcFileElement *)nxe())) { Int_t rc = Add(e->fFirst, e->fLast); if (rc == 1) nadd++; } } // Done return nadd; }