Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:33

0001 // @(#)root/cont:$Id$
0002 // Author: Philippe Canal 20/08/2010
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2003, Rene Brun, Fons Rademakers and al.           *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 
0012 #ifndef ROOT_TVirtualCollectionIterators
0013 #define ROOT_TVirtualCollectionIterators
0014 
0015 /**
0016 \class TVirtualCollectionIterators
0017 \ingroup IO
0018 Small helper class to generically acquire and release iterators.
0019 */
0020 
0021 #include "TVirtualCollectionProxy.h"
0022 #include "TError.h"
0023 #include <vector>
0024 
0025 class TVirtualCollectionIterators
0026 {
0027 private:
0028    TVirtualCollectionIterators() = delete; // Intentionally unimplemented.
0029    TVirtualCollectionIterators(const TVirtualCollectionIterators&) = delete; // Intentionally unimplemented.
0030 
0031 public:
0032    // Note when the collection is a vector, fBegin and fEnd points to
0033    // the start and end of the memory content rather than to the address
0034    // of iterators (saving one dereference when being used).
0035 
0036    typedef TVirtualCollectionProxy::CreateIterators_t CreateIterators_t;
0037    typedef TVirtualCollectionProxy::DeleteTwoIterators_t DeleteTwoIterators_t;
0038 
0039    char  fBeginBuffer[TVirtualCollectionProxy::fgIteratorArenaSize];
0040    char  fEndBuffer[TVirtualCollectionProxy::fgIteratorArenaSize];
0041    void *fBegin; // Pointer to the starting iterator (collection->begin())
0042    void *fEnd;   // Pointer to the ending iterator (collection->end())
0043    CreateIterators_t    fCreateIterators;
0044    DeleteTwoIterators_t fDeleteTwoIterators;
0045 
0046    TVirtualCollectionIterators(TVirtualCollectionProxy *proxy, Bool_t read_from_file = kTRUE) : fBegin( &(fBeginBuffer[0]) ), fEnd(&(fEndBuffer[0])), fCreateIterators(nullptr), fDeleteTwoIterators(nullptr)
0047    {
0048       // Constructor given a collection proxy.
0049 
0050       //         memset(fBeginBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize);
0051       //         memset(fEndBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize);
0052       if (proxy) {
0053          fCreateIterators = proxy->GetFunctionCreateIterators(read_from_file);
0054          fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators(read_from_file);
0055       } else {
0056          ::Fatal("TIterators::TIterators","Created with out a collection proxy!\n");
0057       }
0058    }
0059 
0060    TVirtualCollectionIterators(CreateIterators_t creator, DeleteTwoIterators_t destruct) : fBegin( &(fBeginBuffer[0]) ), fEnd(&(fEndBuffer[0])), fCreateIterators(creator), fDeleteTwoIterators(destruct)
0061    {
0062       // Constructor given the creation and delete routines.
0063    }
0064 
0065    inline void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
0066    {
0067       // Initialize the fBegin and fEnd iterators.
0068 
0069       fCreateIterators(collection, &fBegin, &fEnd, proxy);
0070    }
0071 
0072    inline ~TVirtualCollectionIterators()
0073    {
0074       // Destructor.
0075 
0076       if (fBegin != &(fBeginBuffer[0])) {
0077          // assert(end != endbuf);
0078          fDeleteTwoIterators(fBegin,fEnd);
0079       }
0080    }
0081 };
0082 
0083 
0084 class TGenericCollectionIterator
0085 {
0086 protected:
0087    TVirtualCollectionIterators fIterators;
0088 
0089    // The actual implementation.
0090    class RegularIterator;
0091    class VectorIterator;
0092 
0093    TGenericCollectionIterator() = delete;
0094    TGenericCollectionIterator(const TGenericCollectionIterator&) = delete;
0095 
0096    TGenericCollectionIterator(void *collection, TVirtualCollectionProxy *proxy, Bool_t read_from_file = kTRUE) :
0097       fIterators(proxy,read_from_file)
0098    {
0099       // Regular constructor.
0100 
0101       fIterators.CreateIterators(collection,proxy);
0102    }
0103 
0104    virtual ~TGenericCollectionIterator()
0105    {
0106       // Regular destructor.
0107    }
0108 
0109 public:
0110 
0111    virtual void *Next() = 0;
0112 
0113    virtual void* operator*() const = 0;
0114 
0115    virtual operator bool() const = 0;
0116 
0117    TGenericCollectionIterator& operator++() { Next(); return *this; }
0118 
0119    static TGenericCollectionIterator *New(void *collection, TVirtualCollectionProxy *proxy);
0120 };
0121 
0122 class TGenericCollectionIterator::RegularIterator : public TGenericCollectionIterator {
0123    typedef TVirtualCollectionProxy::Next_t Next_t;
0124 
0125    Next_t    fNext;
0126    void     *fCurrent;
0127    bool      fStarted : 1;
0128 
0129 public:
0130    RegularIterator(void *collection, TVirtualCollectionProxy *proxy, Bool_t read_from_file) :
0131       TGenericCollectionIterator(collection,proxy,read_from_file),
0132       fNext( proxy->GetFunctionNext(read_from_file) ),
0133       fCurrent(nullptr),
0134       fStarted(kFALSE)
0135    {
0136    }
0137 
0138    void *Next() override {
0139       fStarted = kTRUE;
0140       fCurrent = fNext(fIterators.fBegin,fIterators.fEnd);
0141       return fCurrent;
0142    }
0143 
0144    void* operator*() const override { return fCurrent; }
0145 
0146    operator bool() const override { return fStarted ? fCurrent != nullptr : kTRUE; }
0147 
0148 };
0149 
0150 class TGenericCollectionIterator::VectorIterator : public TGenericCollectionIterator {
0151 
0152    ULong_t fIncrement;
0153    Bool_t  fHasPointer;
0154 
0155    inline void *GetValue() const {
0156       if ((bool)*this) return fHasPointer ? *(void**)fIterators.fBegin : fIterators.fBegin;
0157       else return nullptr;
0158    }
0159 
0160 public:
0161    VectorIterator(void *collection, TVirtualCollectionProxy *proxy, Bool_t read_from_file) :
0162       TGenericCollectionIterator(collection,proxy,read_from_file),
0163       fIncrement(proxy->GetIncrement()),
0164       fHasPointer(proxy->HasPointers())
0165    {
0166    }
0167 
0168    void *Next() override {
0169       if ( ! (bool)*this ) return nullptr;
0170       void *result = GetValue();
0171       fIterators.fBegin = ((char*)fIterators.fBegin) + fIncrement;
0172       return result;
0173    }
0174 
0175    void* operator*() const override { return GetValue(); }
0176 
0177    operator bool() const override { return fIterators.fBegin != fIterators.fEnd; }
0178 
0179 };
0180 
0181 inline TGenericCollectionIterator *TGenericCollectionIterator::New(void *collection, TVirtualCollectionProxy *proxy)
0182 {
0183    if (proxy->GetCollectionType() == ROOT::kSTLvector) {
0184       return new VectorIterator(collection, proxy, kFALSE);
0185    } else {
0186       return new RegularIterator(collection, proxy, kFALSE);
0187    }
0188 }
0189 
0190 /**
0191 \class TVirtualCollectionPtrIterators
0192 \ingroup IO
0193 */
0194 class TVirtualCollectionPtrIterators
0195 {
0196 public:
0197    typedef TVirtualCollectionProxy::Next_t Next_t;
0198    typedef TVirtualCollectionProxy::CopyIterator_t Copy_t;
0199    typedef TVirtualCollectionProxy::CreateIterators_t CreateIterators_t;
0200    typedef TVirtualCollectionProxy::DeleteIterator_t Delete_t;
0201    typedef TVirtualCollectionProxy::DeleteTwoIterators_t DeleteTwoIterators_t;
0202 
0203 private:
0204    TVirtualCollectionPtrIterators(); // Intentionally unimplemented.
0205    TVirtualCollectionPtrIterators(const TVirtualCollectionPtrIterators&); // Intentionally unimplemented.
0206 
0207    CreateIterators_t    fCreateIterators;
0208    DeleteTwoIterators_t fDeleteTwoIterators;
0209 
0210    Bool_t fAllocated;
0211 
0212    char  fRawBeginBuffer[TVirtualCollectionProxy::fgIteratorArenaSize];
0213    char  fRawEndBuffer[TVirtualCollectionProxy::fgIteratorArenaSize];
0214 
0215    struct TInternalIterator {
0216    private:
0217       TInternalIterator &operator=(const TInternalIterator&); // intentionally not implemented
0218    public:
0219       TInternalIterator() : fCopy(nullptr), fDelete(nullptr), fNext(nullptr), fIter(nullptr) {}
0220       TInternalIterator(const TInternalIterator &source) : fCopy(source.fCopy), fDelete(source.fDelete), fNext(source.fNext), fIter(nullptr) {}
0221 
0222       Copy_t    fCopy;
0223       Delete_t  fDelete;
0224       Next_t    fNext;
0225 
0226       void     *fIter;
0227    };
0228 
0229    TInternalIterator fBeginBuffer;
0230    TInternalIterator fEndBuffer;
0231 
0232 public:
0233    // Note when the collection is a vector, fBegin and fEnd points to
0234    // the start and end of the memory content rather than to the address
0235    // of iterators (saving one dereference when being used).
0236 
0237    void *fBegin; // Pointer to the starting iterator (collection->begin())
0238    void *fEnd;   // Pointer to the ending iterator (collection->end())
0239 
0240    TVirtualCollectionPtrIterators(TVirtualCollectionProxy *proxy) : fCreateIterators(nullptr), fDeleteTwoIterators(nullptr), fAllocated(kFALSE),
0241                                                                     fBegin( &(fRawBeginBuffer[0]) ),
0242                                                                     fEnd( &(fRawEndBuffer[0]) )
0243    {
0244       //         memset(fBeginBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize);
0245       //         memset(fEndBuffer,0,TVirtualCollectionProxy::fgIteratorArenaSize);
0246       if (proxy) {
0247          fCreateIterators = proxy->GetFunctionCreateIterators();
0248          fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
0249 
0250          fEndBuffer.fCopy = fBeginBuffer.fCopy = proxy->GetFunctionCopyIterator();
0251          fEndBuffer.fNext = fBeginBuffer.fNext = proxy->GetFunctionNext();
0252          fEndBuffer.fDelete = fBeginBuffer.fDelete = proxy->GetFunctionDeleteIterator();
0253       } else {
0254          ::Fatal("TIterators::TIterators","Created with out a collection proxy!\n");
0255       }
0256    }
0257 
0258    inline void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
0259    {
0260       // Initialize the fBegin and fEnd iterators.
0261 
0262       fBegin = &(fRawBeginBuffer[0]);
0263       fEnd = &(fRawEndBuffer[0]);
0264       fCreateIterators(collection, &fBegin, &fEnd, proxy);
0265       if (fBegin != &(fRawBeginBuffer[0])) {
0266          // The iterator where too large to buffer in the  buffer
0267          fAllocated = kTRUE;
0268       }
0269       fBeginBuffer.fIter = fBegin;
0270       fEndBuffer.fIter = fEnd;
0271       fBegin = &fBeginBuffer;
0272       fEnd = &fEndBuffer;
0273    }
0274 
0275    inline ~TVirtualCollectionPtrIterators()
0276    {
0277       if (fAllocated) {
0278          // assert(end != endbuf);
0279          fDeleteTwoIterators(fBeginBuffer.fIter,fEndBuffer.fIter);
0280       }
0281    }
0282 
0283    static void *Next(void *iter, const void *end)
0284    {
0285       TInternalIterator *internal_iter = (TInternalIterator*) iter;
0286       TInternalIterator *internal_end = (TInternalIterator*) end;
0287 
0288       void **ptr = (void**)internal_iter->fNext(internal_iter->fIter,internal_end->fIter);
0289       if(ptr) return *ptr;
0290       else return nullptr;
0291    }
0292 
0293    static void DeleteIterator(void *iter)
0294    {
0295       TInternalIterator *internal_iter = (TInternalIterator*) iter;
0296       if (internal_iter->fDelete) {
0297          internal_iter->fDelete(internal_iter->fIter);
0298       }
0299    }
0300 
0301    static void *CopyIterator(void *dest, const void *source)
0302    {
0303       TInternalIterator *internal_source = (TInternalIterator*)source;
0304       TInternalIterator *internal_dest = new TInternalIterator(*internal_source);
0305 
0306       void *newiter = internal_source->fCopy(dest,internal_source->fIter);
0307       if (newiter == dest) {
0308          internal_dest->fDelete = nullptr;
0309       }
0310       internal_dest->fIter = newiter;
0311       return internal_dest;
0312    }
0313 };
0314 
0315 // Specialization of TVirtualCollectionIterators when we know the collection
0316 // to be a vector (hence there is nothing to delete at the end).
0317 struct TVirtualVectorIterators
0318 {
0319 private:
0320    TVirtualVectorIterators(const TVirtualVectorIterators&); // Intentionally unimplemented.
0321 
0322 public:
0323    // Note when the collection is a vector, fBegin and fEnd points to
0324    // the start and end of the memory content rather than to the address
0325    // of iterators (saving one dereference when being used).
0326 
0327    typedef TVirtualCollectionProxy::CreateIterators_t CreateIterators_t;
0328 
0329    void *fBegin; // Pointer to the starting iterator (collection->begin())
0330    void *fEnd;   // Pointer to the ending iterator (collection->end())
0331 
0332    TVirtualVectorIterators(TVirtualCollectionProxy * /* proxy */) : fBegin(nullptr), fEnd(nullptr)
0333    {
0334       // fCreateIterators = proxy->GetFunctionCreateIterators();
0335    }
0336 
0337    TVirtualVectorIterators(CreateIterators_t /* creator */) : fBegin(nullptr), fEnd(nullptr)
0338    {
0339       // fCreateIterators = creator;
0340    }
0341 
0342    TVirtualVectorIterators() : fBegin(nullptr), fEnd(nullptr)
0343    {
0344       // Default constructor.
0345    }
0346 
0347    inline void CreateIterators(void *collection)
0348    {
0349       // Initialize the fBegin and fEnd iterators.
0350 
0351       // We can safely assume that the std::vector layout does not really depend on
0352       // the content!
0353       std::vector<char> *vec = (std::vector<char>*)collection;
0354       if (vec->empty()) {
0355          fBegin = nullptr;
0356          fEnd = nullptr;
0357          return;
0358       }
0359       fBegin= &(*vec->begin());
0360 #ifdef R__VISUAL_CPLUSPLUS
0361       fEnd = &(*(vec->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
0362 #else
0363       // coverity[past_the_end] Safe on other platforms
0364       fEnd = &(*vec->end());
0365 #endif
0366       //fCreateIterators(collection, &fBegin, &fEnd);
0367    }
0368 };
0369 
0370 #endif // ROOT_TVirtualCollectionIterators
0371