From 0dcc7c5afbd9f1b52a431014543d97386b5d8514 Mon Sep 17 00:00:00 2001 From: Axel Naumann Date: Wed, 27 Aug 2014 11:13:44 +0200 Subject: [PATCH] Add iterator interface for TTreeReader. We want sequential reads, thus use a forward iterator. The iterator does not really reference any data but the tree entry number so return that as the deref-op. The same operator (also called from the increment operators) sets its entry number in the associated TTreeReader. This iterator is "C++14 safe" in that its past-end-iterator can be value constructed and all past-end-iterators compare equal. --- tree/treeplayer/inc/TTreeReader.h | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tree/treeplayer/inc/TTreeReader.h b/tree/treeplayer/inc/TTreeReader.h index 9323862..baafa58 100644 --- a/tree/treeplayer/inc/TTreeReader.h +++ b/tree/treeplayer/inc/TTreeReader.h @@ -33,6 +33,7 @@ #endif #include +#include class TDictionary; class TDirectory; @@ -45,6 +46,77 @@ namespace ROOT { class TTreeReader: public TObject { public: + // Iterate through the entries of a TTree. + // + // This iterator drives the associated TTreeReader; its + // dereferencing (and actually even the iteration) will + // set the entry number represented by this iterator. + // It does not really represent a data element; it simply + // returns the entry number (or -1 once the end of the tree + // is reached). + class Iterator_t: + public std::iterator { + private: + Long64_t fEntry; // Entry number of the tree referenced by this iterator; -1 is invalid. + TTreeReader* fReader; // The reader we select the entries on. + + // Whether the iterator points to a valid entry. + bool IsValid() const { return fEntry >= 0; } + + public: + // Default-initialize the iterator as "past the end". + Iterator_t(): fEntry(-1), fReader() {} + + // Initialize the iterator with the reader it steers and a + // tree entry number; -1 is invalid. + Iterator_t(TTreeReader& reader, Long64_t entry): + fEntry(entry), fReader(&reader) {} + + bool operator==(const Iterator_t& lhs) const { + // Compare two iterators for equality. + // From C++14: value initialized (past-end) it compare equal. + if (!IsValid() && !lhs.IsValid()) return true; + return fEntry == lhs.fEntry && fReader == lhs.fReader; + } + + bool operator!=(const Iterator_t& lhs) const { + // Compare two iterators for inequality. + return !(*this == lhs); + } + + Iterator_t operator++(int) { + // Increment the iterator (postfix i++). + Iterator_t ret = *this; + this->operator++(); + return ret; + } + + Iterator_t& operator++() { + // Increment the iterator (prefix ++i). + if (IsValid()) { + ++fEntry; + // Force validity check of new fEntry. + this->operator*(); + // Don't set the old entry: op* will if needed, and + // in most cases it just adds a lot of spinning back + // and forth: in most cases teh sequence is ++i; *i. + } + return *this; + } + + Long64_t operator*() { + // Set the entry number in the reader and return it. + if (IsValid()) { + // If we cannot access that entry, mark the iterator invalid. + if (fReader->SetEntry(fEntry) != kEntryValid) { + fEntry = -1; + } + } + // There really is no data in this iterator; return the number. + return fEntry; + } + }; + enum EEntryStatus { kEntryValid = 0, // data read okay kEntryNotLoaded, // no entry has been loaded yet @@ -83,6 +155,12 @@ public: Long64_t GetEntries(Bool_t force) const { return fTree ? (force ? fTree->GetEntries() : fTree->GetEntriesFast() ) : -1; } Long64_t GetCurrentEntry() const; + Iterator_t begin() { + // Return an iterator to the 0th TTree entry. + return Iterator_t(*this, 0); + } + Iterator_t end() const { return Iterator_t(); } + protected: void Initialize(); ROOT::TNamedBranchProxy* FindProxy(const char* branchname) const { -- 1.8.2