// @(#)root/tree:$Id$
// Author: Axel Naumann, 2010-08-02

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

#ifndef ROOT_TTreeReaderArray
#define ROOT_TTreeReaderArray


////////////////////////////////////////////////////////////////////////////
//                                                                        //
// TTreeReaderArray                                                    //
//                                                                        //
// A simple interface for reading data from trees or chains.              //
//                                                                        //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

#ifndef ROOT_TTreeReaderValue
#include "TTreeReaderValue.h"
#endif
#ifndef ROOT_TTreeReaderUtils
#include "TTreeReaderUtils.h"
#endif

namespace ROOT {
   class TTreeReaderArrayBase: public TTreeReaderValueBase {
   public:
      TTreeReaderArrayBase(TTreeReader* reader, const char* branchname,
                           TDictionary* dict):
         TTreeReaderValueBase(reader, branchname, dict), fImpl(0) {}

      size_t GetSize() const { return fImpl->GetSize(GetProxy()); }
      Bool_t IsEmpty() const { return !GetSize(); }

      virtual EReadStatus GetReadStatus() const { return fImpl ? fImpl->fReadStatus : kReadError; }

   protected:
      void* UntypedAt(size_t idx) const { return fImpl->At(GetProxy(), idx); }
      virtual void CreateProxy();
      const char* GetBranchContentDataType(TBranch* branch,
                                           TString& contentTypeName,
                                           TDictionary* &dict) const;

      TVirtualCollectionReader* fImpl; // Common interface to collections

      // FIXME: re-introduce once we have ClassDefInline!
      //ClassDef(TTreeReaderArrayBase, 0);//Accessor to member of an object stored in a collection
   };

} // namespace ROOT

template <typename T>
class TTreeReaderArray: public ROOT::TTreeReaderArrayBase {
public:

   // Iterator through the indices of a TTreeReaderArray.
   struct Iterator_t:
      public std::iterator<std::input_iterator_tag, T, long> {
      // Default initialized, past-end iterator.
      Iterator_t() :
         fIndex(0), fArray(0) {}

      // Initialize with an array and index.
      Iterator_t(size_t idx, TTreeReaderArray* array) :
         fIndex(idx), fArray(array) {}

      size_t fIndex; // Current index in the array.
      TTreeReaderArray* fArray; // The array iterated over; 0 if invalid / end.

      bool IsValid() const { return fArray; }

      bool operator==(const Iterator_t& lhs) const {
         // Compare two iterators as equal; follow C++14 requiring two past-end
         // iterators to be equal.
         if (!IsValid() && !lhs.IsValid())
            return true;
         return fIndex == lhs.fIndex && fArray == lhs.fArray;
      }

      bool operator!=(const Iterator_t& lhs) const {
         // Compare not equal.
         return !(*this == lhs);
      }

      Iterator_t operator++(int) {
         // Post-increment (it++).
         Iterator_t ret = *this;
         this->operator++();
         return ret;
      }

      Iterator_t& operator++() {
         // Pre-increment (++it).
         if (IsValid()) {
            ++fIndex;
            if (fIndex >= fArray->GetSize()) {
               // Remember that it's past-end.
               fArray = 0;
            }
         }
         return *this;
      }

      T& operator*() const {
         // Get the referenced element.
         R__ASSERT(fArray && "invalid iterator!");
         return fArray->At(fIndex);
      }
   };

   typedef Iterator_t iterator;

   TTreeReaderArray(TTreeReader& tr, const char* branchname):
      TTreeReaderArrayBase(&tr, branchname, TDictionary::GetDictionary(typeid(T)))
   {
      // Create an array reader of branch "branchname" for TTreeReader "tr".
   }

   T& At(size_t idx) { return *(T*)UntypedAt(idx); }
   T& operator[](size_t idx) { return At(idx); }

   Iterator_t begin() {
      // Return an iterator to the 0th TTree entry or an empty iterator if the
      // array is empty.
      return IsEmpty() ? Iterator_t() : Iterator_t(0, this);
   }
   Iterator_t end() const { return Iterator_t(); }

protected:
#define R__TTreeReaderArray_TypeString(T) #T
   virtual const char* GetDerivedTypeName() const { return R__TTreeReaderArray_TypeString(T); }
#undef R__TTreeReaderArray_TypeString
   // FIXME: re-introduce once we have ClassDefTInline!
   //ClassDefT(TTreeReaderArray, 0);//Accessor to member of an object stored in a collection
};

#endif // ROOT_TTreeReaderArray
 TTreeReaderArray.h:1
 TTreeReaderArray.h:2
 TTreeReaderArray.h:3
 TTreeReaderArray.h:4
 TTreeReaderArray.h:5
 TTreeReaderArray.h:6
 TTreeReaderArray.h:7
 TTreeReaderArray.h:8
 TTreeReaderArray.h:9
 TTreeReaderArray.h:10
 TTreeReaderArray.h:11
 TTreeReaderArray.h:12
 TTreeReaderArray.h:13
 TTreeReaderArray.h:14
 TTreeReaderArray.h:15
 TTreeReaderArray.h:16
 TTreeReaderArray.h:17
 TTreeReaderArray.h:18
 TTreeReaderArray.h:19
 TTreeReaderArray.h:20
 TTreeReaderArray.h:21
 TTreeReaderArray.h:22
 TTreeReaderArray.h:23
 TTreeReaderArray.h:24
 TTreeReaderArray.h:25
 TTreeReaderArray.h:26
 TTreeReaderArray.h:27
 TTreeReaderArray.h:28
 TTreeReaderArray.h:29
 TTreeReaderArray.h:30
 TTreeReaderArray.h:31
 TTreeReaderArray.h:32
 TTreeReaderArray.h:33
 TTreeReaderArray.h:34
 TTreeReaderArray.h:35
 TTreeReaderArray.h:36
 TTreeReaderArray.h:37
 TTreeReaderArray.h:38
 TTreeReaderArray.h:39
 TTreeReaderArray.h:40
 TTreeReaderArray.h:41
 TTreeReaderArray.h:42
 TTreeReaderArray.h:43
 TTreeReaderArray.h:44
 TTreeReaderArray.h:45
 TTreeReaderArray.h:46
 TTreeReaderArray.h:47
 TTreeReaderArray.h:48
 TTreeReaderArray.h:49
 TTreeReaderArray.h:50
 TTreeReaderArray.h:51
 TTreeReaderArray.h:52
 TTreeReaderArray.h:53
 TTreeReaderArray.h:54
 TTreeReaderArray.h:55
 TTreeReaderArray.h:56
 TTreeReaderArray.h:57
 TTreeReaderArray.h:58
 TTreeReaderArray.h:59
 TTreeReaderArray.h:60
 TTreeReaderArray.h:61
 TTreeReaderArray.h:62
 TTreeReaderArray.h:63
 TTreeReaderArray.h:64
 TTreeReaderArray.h:65
 TTreeReaderArray.h:66
 TTreeReaderArray.h:67
 TTreeReaderArray.h:68
 TTreeReaderArray.h:69
 TTreeReaderArray.h:70
 TTreeReaderArray.h:71
 TTreeReaderArray.h:72
 TTreeReaderArray.h:73
 TTreeReaderArray.h:74
 TTreeReaderArray.h:75
 TTreeReaderArray.h:76
 TTreeReaderArray.h:77
 TTreeReaderArray.h:78
 TTreeReaderArray.h:79
 TTreeReaderArray.h:80
 TTreeReaderArray.h:81
 TTreeReaderArray.h:82
 TTreeReaderArray.h:83
 TTreeReaderArray.h:84
 TTreeReaderArray.h:85
 TTreeReaderArray.h:86
 TTreeReaderArray.h:87
 TTreeReaderArray.h:88
 TTreeReaderArray.h:89
 TTreeReaderArray.h:90
 TTreeReaderArray.h:91
 TTreeReaderArray.h:92
 TTreeReaderArray.h:93
 TTreeReaderArray.h:94
 TTreeReaderArray.h:95
 TTreeReaderArray.h:96
 TTreeReaderArray.h:97
 TTreeReaderArray.h:98
 TTreeReaderArray.h:99
 TTreeReaderArray.h:100
 TTreeReaderArray.h:101
 TTreeReaderArray.h:102
 TTreeReaderArray.h:103
 TTreeReaderArray.h:104
 TTreeReaderArray.h:105
 TTreeReaderArray.h:106
 TTreeReaderArray.h:107
 TTreeReaderArray.h:108
 TTreeReaderArray.h:109
 TTreeReaderArray.h:110
 TTreeReaderArray.h:111
 TTreeReaderArray.h:112
 TTreeReaderArray.h:113
 TTreeReaderArray.h:114
 TTreeReaderArray.h:115
 TTreeReaderArray.h:116
 TTreeReaderArray.h:117
 TTreeReaderArray.h:118
 TTreeReaderArray.h:119
 TTreeReaderArray.h:120
 TTreeReaderArray.h:121
 TTreeReaderArray.h:122
 TTreeReaderArray.h:123
 TTreeReaderArray.h:124
 TTreeReaderArray.h:125
 TTreeReaderArray.h:126
 TTreeReaderArray.h:127
 TTreeReaderArray.h:128
 TTreeReaderArray.h:129
 TTreeReaderArray.h:130
 TTreeReaderArray.h:131
 TTreeReaderArray.h:132
 TTreeReaderArray.h:133
 TTreeReaderArray.h:134
 TTreeReaderArray.h:135
 TTreeReaderArray.h:136
 TTreeReaderArray.h:137
 TTreeReaderArray.h:138
 TTreeReaderArray.h:139
 TTreeReaderArray.h:140
 TTreeReaderArray.h:141
 TTreeReaderArray.h:142
 TTreeReaderArray.h:143
 TTreeReaderArray.h:144