#ifndef ROOT_TEveChunkManager
#define ROOT_TEveChunkManager
#include "TEveUtil.h"
#include "TObject.h"
#include "TArrayC.h"
#include <vector>
class TEveChunkManager
{
private:
TEveChunkManager(const TEveChunkManager&);
TEveChunkManager& operator=(const TEveChunkManager&);
protected:
Int_t fS;
Int_t fN;
Int_t fSize;
Int_t fVecSize;
Int_t fCapacity;
std::vector<TArrayC*> fChunks;
void ReleaseChunks();
public:
TEveChunkManager();
TEveChunkManager(Int_t atom_size, Int_t chunk_size);
virtual ~TEveChunkManager();
void Reset(Int_t atom_size, Int_t chunk_size);
void Refit();
Int_t S() const { return fS; }
Int_t N() const { return fN; }
Int_t Size() const { return fSize; }
Int_t VecSize() const { return fVecSize; }
Int_t Capacity() const { return fCapacity; }
Char_t* Atom(Int_t idx) const { return fChunks[idx/fN]->fArray + idx%fN*fS; }
Char_t* Chunk(Int_t chk) const { return fChunks[chk]->fArray; }
Int_t NAtoms(Int_t chk) const { return (chk < fVecSize-1) ? fN : (fSize-1)%fN + 1; }
Char_t* NewAtom();
Char_t* NewChunk();
struct iterator
{
TEveChunkManager *fPlex;
Char_t *fCurrent;
Int_t fAtomIndex;
Int_t fNextChunk;
Int_t fAtomsToGo;
iterator(TEveChunkManager* p) :
fPlex(p), fCurrent(0), fAtomIndex(-1), fNextChunk(0), fAtomsToGo(0) {}
iterator(TEveChunkManager& p) :
fPlex(&p), fCurrent(0), fAtomIndex(-1), fNextChunk(0), fAtomsToGo(0) {}
iterator(const iterator& i) :
fPlex(i.fPlex), fCurrent(i.fCurrent), fAtomIndex(i.fAtomIndex), fNextChunk(i.fNextChunk), fAtomsToGo(i.fAtomsToGo) {}
iterator& operator=(const iterator& i)
{ fPlex = i.fPlex; fCurrent = i.fCurrent; fAtomIndex = i.fAtomIndex; fNextChunk = i.fNextChunk; fAtomsToGo = i.fAtomsToGo; return *this; }
Bool_t next();
void reset() { fCurrent = 0; fNextChunk = fAtomsToGo = 0; }
Char_t* operator()() { return fCurrent; }
Char_t* operator*() { return fCurrent; }
Int_t index() { return fAtomIndex; }
};
ClassDef(TEveChunkManager, 1);
};
inline Char_t* TEveChunkManager::NewAtom()
{
Char_t *a = (fSize >= fCapacity) ? NewChunk() : Atom(fSize);
++fSize;
return a;
}
inline Bool_t TEveChunkManager::iterator::next()
{
if (fAtomsToGo <= 0) {
if (fNextChunk < fPlex->VecSize()) {
fCurrent = fPlex->Chunk(fNextChunk);
fAtomsToGo = fPlex->NAtoms(fNextChunk);
++fNextChunk;
} else {
return kFALSE;
}
} else {
fCurrent += fPlex->S();
}
++fAtomIndex;
--fAtomsToGo;
return kTRUE;
}
template<class T>
class TEveChunkVector : public TEveChunkManager
{
private:
TEveChunkVector(const TEveChunkVector&);
TEveChunkVector& operator=(const TEveChunkVector&);
public:
TEveChunkVector() : TEveChunkManager() {}
TEveChunkVector(Int_t chunk_size) : TEveChunkManager(sizeof(T), chunk_size) {}
virtual ~TEveChunkVector() {}
void Reset(Int_t chunk_size) { Reset(sizeof(T), chunk_size); }
T* At(Int_t idx) { return reinterpret_cast<T*>(Atom(idx)); }
T& Ref(Int_t idx) { return *At(idx); }
ClassDef(TEveChunkVector, 1);
};
#endif