// @(#)root/cont:$Id: e00edea30f17233d3f97a85eba14e20c201eb980 $ // Author: Philippe Canal 20/08/2010 /************************************************************************* * Copyright (C) 1995-2003, Rene Brun, Fons Rademakers and al. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #ifndef ROOT_TVirtualCollectionIterators #define ROOT_TVirtualCollectionIterators ////////////////////////////////////////////////////////////////////////// // // // TVirtualCollectionIterators // // // // Small helper class to generically acquire and release iterators // // // ////////////////////////////////////////////////////////////////////////// #ifndef ROOT_TVirtualCollectionProxy #include "TVirtualCollectionProxy.h" #endif #ifndef ROOT_TError #include "TError.h" #endif class TVirtualCollectionIterators { private: TVirtualCollectionIterators(); // Intentionally unimplemented. TVirtualCollectionIterators(const TVirtualCollectionIterators&); // Intentionally unimplemented. public: // Note when the collection is a vector, fBegin and fEnd points to // the start and end of the memory content rather than to the address // of iterators (saving one dereference when being used). typedef TVirtualCollectionProxy::CreateIterators_t CreateIterators_t; typedef TVirtualCollectionProxy::DeleteTwoIterators_t DeleteTwoIterators_t; char fBeginBuffer[TVirtualCollectionProxy::fgIteratorArenaSize]; char fEndBuffer[TVirtualCollectionProxy::fgIteratorArenaSize]; void *fBegin; // Pointer to the starting iterator (collection->begin()) void *fEnd; // Pointer to the ending iterator (collection->end()) CreateIterators_t fCreateIterators; DeleteTwoIterators_t fDeleteTwoIterators; TVirtualCollectionIterators(TVirtualCollectionProxy *proxy, Bool_t read = kTRUE) : fBegin( &(fBeginBuffer[0]) ), fEnd(&(fEndBuffer[0])), fCreateIterators(0), fDeleteTwoIterators(0) { // memset(fBeginBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize); // memset(fEndBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize); if (proxy) { fCreateIterators = proxy->GetFunctionCreateIterators(read); fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators(read); } else { ::Fatal("TIterators::TIterators","Created with out a collection proxy!\n"); } } TVirtualCollectionIterators(CreateIterators_t creator, DeleteTwoIterators_t destruct) : fBegin( &(fBeginBuffer[0]) ), fEnd(&(fEndBuffer[0])), fCreateIterators(creator), fDeleteTwoIterators(destruct) { } inline void CreateIterators(void *collection, TVirtualCollectionProxy *proxy) { // Initialize the fBegin and fEnd iterators. fCreateIterators(collection, &fBegin, &fEnd, proxy); } inline ~TVirtualCollectionIterators() { if (fBegin != &(fBeginBuffer[0])) { // assert(end != endbuf); fDeleteTwoIterators(fBegin,fEnd); } } }; class TVirtualCollectionPtrIterators { public: typedef TVirtualCollectionProxy::Next_t Next_t; typedef TVirtualCollectionProxy::CopyIterator_t Copy_t; typedef TVirtualCollectionProxy::CreateIterators_t CreateIterators_t; typedef TVirtualCollectionProxy::DeleteIterator_t Delete_t; typedef TVirtualCollectionProxy::DeleteTwoIterators_t DeleteTwoIterators_t; private: TVirtualCollectionPtrIterators(); // Intentionally unimplemented. TVirtualCollectionPtrIterators(const TVirtualCollectionPtrIterators&); // Intentionally unimplemented. CreateIterators_t fCreateIterators; DeleteTwoIterators_t fDeleteTwoIterators; Bool_t fAllocated; char fRawBeginBuffer[TVirtualCollectionProxy::fgIteratorArenaSize]; char fRawEndBuffer[TVirtualCollectionProxy::fgIteratorArenaSize]; struct TInternalIterator { private: TInternalIterator &operator=(const TInternalIterator&); // intentionally not implemented public: TInternalIterator() : fCopy(0),fDelete(0),fNext(0),fIter(0) {} TInternalIterator(const TInternalIterator &source) : fCopy(source.fCopy),fDelete(source.fDelete),fNext(source.fNext),fIter(0) {} Copy_t fCopy; Delete_t fDelete; Next_t fNext; void *fIter; }; TInternalIterator fBeginBuffer; TInternalIterator fEndBuffer; public: // Note when the collection is a vector, fBegin and fEnd points to // the start and end of the memory content rather than to the address // of iterators (saving one dereference when being used). void *fBegin; // Pointer to the starting iterator (collection->begin()) void *fEnd; // Pointer to the ending iterator (collection->end()) TVirtualCollectionPtrIterators(TVirtualCollectionProxy *proxy) : fCreateIterators(0), fDeleteTwoIterators(0), fAllocated(kFALSE), fBegin( &(fRawBeginBuffer[0]) ), fEnd( &(fRawEndBuffer[0]) ) { // memset(fBeginBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize); // memset(fEndBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize); if (proxy) { fCreateIterators = proxy->GetFunctionCreateIterators(); fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators(); fEndBuffer.fCopy = fBeginBuffer.fCopy = proxy->GetFunctionCopyIterator(); fEndBuffer.fNext = fBeginBuffer.fNext = proxy->GetFunctionNext(); fEndBuffer.fDelete = fBeginBuffer.fDelete = proxy->GetFunctionDeleteIterator(); } else { ::Fatal("TIterators::TIterators","Created with out a collection proxy!\n"); } } inline void CreateIterators(void *collection, TVirtualCollectionProxy *proxy) { // Initialize the fBegin and fEnd iterators. fBegin = &(fRawBeginBuffer[0]); fEnd = &(fRawEndBuffer[0]); fCreateIterators(collection, &fBegin, &fEnd, proxy); if (fBegin != &(fRawBeginBuffer[0])) { // The iterator where too large to buffer in the buffer fAllocated = kTRUE; } fBeginBuffer.fIter = fBegin; fEndBuffer.fIter = fEnd; fBegin = &fBeginBuffer; fEnd = &fEndBuffer; } inline ~TVirtualCollectionPtrIterators() { if (fAllocated) { // assert(end != endbuf); fDeleteTwoIterators(fBeginBuffer.fIter,fEndBuffer.fIter); } } static void *Next(void *iter, const void *end) { TInternalIterator *internal_iter = (TInternalIterator*) iter; TInternalIterator *internal_end = (TInternalIterator*) end; void **ptr = (void**)internal_iter->fNext(internal_iter->fIter,internal_end->fIter); if(ptr) return *ptr; else return 0; } static void DeleteIterator(void *iter) { TInternalIterator *internal_iter = (TInternalIterator*) iter; if (internal_iter->fDelete) { internal_iter->fDelete(internal_iter->fIter); } } static void *CopyIterator(void *dest, const void *source) { TInternalIterator *internal_source = (TInternalIterator*)source; TInternalIterator *internal_dest = new TInternalIterator(*internal_source); void *newiter = internal_source->fCopy(dest,internal_source->fIter); if (newiter == dest) { internal_dest->fDelete = 0; } internal_dest->fIter = newiter; return internal_dest; } }; // Specialization of TVirtualCollectionIterators when we know the collection // to be a vector (hence there is nothing to delete at the end). struct TVirtualVectorIterators { private: TVirtualVectorIterators(const TVirtualVectorIterators&); // Intentionally unimplemented. public: // Note when the collection is a vector, fBegin and fEnd points to // the start and end of the memory content rather than to the address // of iterators (saving one dereference when being used). typedef TVirtualCollectionProxy::CreateIterators_t CreateIterators_t; void *fBegin; // Pointer to the starting iterator (collection->begin()) void *fEnd; // Pointer to the ending iterator (collection->end()) TVirtualVectorIterators(TVirtualCollectionProxy * /* proxy */) : fBegin(0), fEnd(0) { // fCreateIterators = proxy->GetFunctionCreateIterators(); } TVirtualVectorIterators(CreateIterators_t /* creator */) : fBegin(0), fEnd(0) { // fCreateIterators = creator; } TVirtualVectorIterators() : fBegin(0), fEnd(0) { // Default constructor. } inline void CreateIterators(void *collection) { // Initialize the fBegin and fEnd iterators. // We can safely assume that the std::vector layout does not really depend on // the content! std::vector *vec = (std::vector*)collection; if (vec->empty()) { fBegin = 0; fEnd = 0; return; } fBegin= &(*vec->begin()); #ifdef R__VISUAL_CPLUSPLUS fEnd = &(*(vec->end()-1)) + 1; // On windows we can not dererence the end iterator at all. #else // coverity[past_the_end] Safe on other platforms fEnd = &(*vec->end()); #endif //fCreateIterators(collection, &fBegin, &fEnd); } }; #endif // ROOT_TVirtualCollectionIterators