// @(#)root/table:$Name:  $:$Id: TIndexTable.h,v 1.3 2004/02/13 14:27:00 rdm Exp $
// Author: Valery Fine(fine@bnl.gov)   01/03/2001

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * Copyright (C) 2001 [BNL] Brookhaven National Laboratory.              *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TIndexTable
#define ROOT_TIndexTable

#ifndef ROOT_TTable
#include "TTable.h"
#endif

//////////////////////////////////////////////////////
//
// Class TIndexTable
// Iterator of the table with extra index array
//
//////////////////////////////////////////////////////


class TIndexTable : public TTable
{
protected:
   const TTable *fRefTable;
public:
   class iterator {
   protected:
      const TTable *fTable;
      int   *fCurrentRow;
      iterator(): fTable(0), fCurrentRow(0) {}
   public:
      iterator(const TTable &t, int &rowPtr): fTable(&t), fCurrentRow(&rowPtr){}
      iterator(const TTable &t): fTable(&t),fCurrentRow(0){}
      iterator(const iterator& iter) : fTable(iter.fTable), fCurrentRow(iter.fCurrentRow){}
      iterator &operator=(const iterator& iter) {fTable = iter.fTable; fCurrentRow = iter.fCurrentRow; return *this;}
      iterator &operator++()    { if (fCurrentRow) ++fCurrentRow; return *this;}
      void     operator++(int)  { if (fCurrentRow) fCurrentRow++;}
      iterator &operator--()    { if (fCurrentRow) --fCurrentRow; return *this;}
      void     operator--(int) { if (fCurrentRow) fCurrentRow--;}
      iterator &operator+(Int_t idx) { if (fCurrentRow) fCurrentRow+=idx; return *this;}
      iterator &operator-(Int_t idx) { if (fCurrentRow) fCurrentRow-=idx; return *this;}
      Int_t operator-(const iterator &it) const { return (fCurrentRow-it.fCurrentRow)/sizeof(int); }
      void *operator *(){ return (void *)(fTable?((char *)fTable->GetArray())+(*fCurrentRow)*(fTable->GetRowSize()):0);}
      operator int()  { return *fCurrentRow;}
      Bool_t operator==(const iterator &t) const { return (fCurrentRow == t.fCurrentRow); }
      Bool_t operator!=(const iterator &t) const { return !operator==(t); }
   };
   TIndexTable(const TTable *table);
   TIndexTable(const TIndexTable &indx): TTable(indx){}
   int  *GetTable(Int_t i=0);
   Bool_t  IsValid() const;
   void    push_back(Long_t next);

   const TTable *Table() const;
   iterator begin()        { return ((const TIndexTable *)this)->begin();}
   iterator begin() const  { return GetNRows() ? iterator(*Table(),*(int *)GetTable(0)):end();}
   iterator end()   { return ((const TIndexTable *)this)->end(); }
   iterator end()   const  {Long_t i = GetNRows(); return i? iterator(*Table(), *(int *)GetTable(i)):iterator(*this);}

protected:
   static TTableDescriptor *CreateDescriptor();

// define ClassDefTable(TIndexTable,int)
  protected:
     static TTableDescriptor *fgColDescriptors;
     virtual TTableDescriptor *GetDescriptorPointer() const { return fgColDescriptors;}
     virtual void SetDescriptorPointer(TTableDescriptor *list)  { fgColDescriptors = list;}
  public:
    TIndexTable() : TTable("TIndexTable",sizeof(int))    {SetType("int");}
    TIndexTable(const Text_t *name) : TTable(name,sizeof(int)) {SetType("int");}
    TIndexTable(Int_t n) : TTable("TIndexTable",n,sizeof(int)) {SetType("int");}
    TIndexTable(const Text_t *name,Int_t n) : TTable(name,n,sizeof(int)) {SetType("int");}
    virtual ~TIndexTable() {}
    const int *GetTable(Int_t i=0) const;
    int &operator[](Int_t i){ assert(i>=0 && i < GetNRows()); return *GetTable(i); }
    const int &operator[](Int_t i) const { assert(i>=0 && i < GetNRows()); return *((const int *)(GetTable(i))); }
    ClassDef(TIndexTable,4) // "Index" array for TTable object
};

//___________________________________________________________________________________________________________
inline  int  *TIndexTable::GetTable(Int_t i) { return ((int *)GetArray())+i;}
//___________________________________________________________________________________________________________
inline  const int *TIndexTable::GetTable(Int_t i) const { return ((int *)GetArray())+i;}
//___________________________________________________________________________________________________________
inline  Bool_t TIndexTable::IsValid() const
{
    // Check whether all "map" values do belong the table
    const TTable *cont= Table();
    if (!cont) return kFALSE;

    iterator i      = begin();
    iterator finish = end();
    Int_t totalSize         = cont->GetNRows();

    for (; i != finish; i++) {
       int th = i;
       if (  th == -1 || (0 <= th && th < totalSize) ) continue;
       return kFALSE;
    }
    return kTRUE;
}
//___________________________________________________________________________________________________________
inline void TIndexTable::push_back(Long_t next){ AddAt(&next); }

#endif
