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/2003
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_TVirtualCollectionProxy
0013 #define ROOT_TVirtualCollectionProxy
0014 
0015 //////////////////////////////////////////////////////////////////////////
0016 //                                                                      //
0017 // TVirtualCollectionProxy                                              //
0018 //                                                                      //
0019 // Virtual interface of a proxy object for a collection class           //
0020 // In particular this is used to implement splitting, emulation,        //
0021 // and TTreeFormula access to STL containers.                           //
0022 //                                                                      //
0023 //////////////////////////////////////////////////////////////////////////
0024 
0025 #include "TClassRef.h"
0026 #include "TDataType.h"
0027 
0028 // Macro indicating the version of the Collection Proxy interface followed
0029 // by this ROOT build (See also Reflex/Builder/CollectionProxy.h).
0030 #define ROOT_COLLECTIONPROXY_VERSION 3
0031 
0032 class TClass;
0033 namespace TStreamerInfoActions {
0034    class TActionSequence;
0035 }
0036 
0037 // clang-format off
0038 /**
0039 \class TVirtualCollectionProxy
0040 \brief Defines a common interface to inspect/change the contents of an object that represents a collection
0041 
0042 Specifically, an object of a class that derives from TVirtualCollectionProxy relays accesses to any object that
0043 matches the proxied collection type.
0044 The interface provides two families of functions: (i) for direct manipulation, e.g. `Insert()` or `At()`; and
0045 (ii) iterator-based, e.g. `GetFunctionCreateIterators()` or `GetFunctionNext()`.
0046 TVirtualCollectionProxy objects are stateful; in particular, many functions require to set the object to operate
0047 on via `PushProxy()` / `PopProxy()`.  The `TPushPop` RAII class is provided for convenience.
0048 A collection proxy for a given class can be permanently set using `TClass::CopyCollectionProxy()`.
0049 The `Generate()` function should be overridden in derived classes to return a clean object of the most-derived class.
0050 */
0051 // clang-format on
0052 class TVirtualCollectionProxy {
0053 private:
0054    TVirtualCollectionProxy(const TVirtualCollectionProxy&) = delete;
0055    TVirtualCollectionProxy& operator=(const TVirtualCollectionProxy&) = delete;
0056 
0057 protected:
0058    TClassRef fClass;
0059    UInt_t    fProperties;
0060    friend class TClass;
0061 
0062 public:
0063    enum EProperty {
0064       // No longer used
0065       // kIsInitialized = BIT(1),
0066       kIsAssociative = BIT(2),
0067       kIsEmulated = BIT(3),
0068       /// The collection contains directly or indirectly (via other collection) some pointers that need explicit
0069       /// deletion
0070       kNeedDelete = BIT(4),
0071       kCustomAlloc = BIT(5) ///< The collection has a custom allocator.
0072    };
0073 
0074    /// RAII helper class that ensures that `PushProxy()` / `PopProxy()` are called when entering / leaving a C++ context
0075    class TPushPop {
0076    public:
0077       TVirtualCollectionProxy *fProxy;
0078       inline TPushPop(TVirtualCollectionProxy *proxy,
0079          void *objectstart) : fProxy(proxy) { fProxy->PushProxy(objectstart); }
0080       inline ~TPushPop() { fProxy->PopProxy(); }
0081    private:
0082       TPushPop(const TPushPop&) = delete;
0083       TPushPop& operator=(const TPushPop&) = delete;
0084    };
0085 
0086    TVirtualCollectionProxy() : fClass(), fProperties(0) {}
0087    TVirtualCollectionProxy(TClass *cl) : fClass(cl), fProperties(0) {}
0088    virtual ~TVirtualCollectionProxy() {}
0089 
0090    /// Returns a clean object of the actual class that derives from TVirtualCollectionProxy.  The caller is responsible
0091    /// for deleting the returned object.
0092    virtual TVirtualCollectionProxy *Generate() const = 0;
0093 
0094    /// Reset the information gathered from StreamerInfos and value's TClass.
0095    virtual Bool_t    Reset() { return kTRUE; }
0096 
0097    /// Return a pointer to the `TClass` representing the proxied _container_ class
0098    virtual TClass *GetCollectionClass() const { return fClass; }
0099 
0100    /// Return the type of the proxied collection (see enumeration TClassEdit::ESTLType)
0101    virtual Int_t GetCollectionType() const = 0;
0102 
0103    /// Return the offset between two consecutive in-memory values (which depends on the `sizeof()` and alignment of the
0104    /// value type).
0105    virtual ULong_t GetIncrement() const = 0;
0106 
0107    /// Return miscallenous properties of the proxy (see TVirtualCollectionProxy::EProperty)
0108    virtual Int_t GetProperties() const { return fProperties; }
0109 
0110    /// Construct a new container object and return its address
0111    virtual void *New() const { return !fClass.GetClass() ? nullptr : fClass->New(); }
0112    /// Construct a new container object at the address given by `arena`
0113    virtual void *New(void *arena) const { return !fClass.GetClass() ? nullptr : fClass->New(arena); }
0114    /// Construct a new container object and return its address
0115    virtual TClass::ObjectPtr NewObject() const
0116    {
0117       return !fClass.GetClass() ? TClass::ObjectPtr{} : fClass->NewObject();
0118    }
0119    /// Construct a new container object at the address given by `arena`
0120    virtual TClass::ObjectPtr NewObject(void *arena) const
0121    {
0122       return !fClass.GetClass() ? TClass::ObjectPtr{} : fClass->NewObject(arena);
0123    }
0124 
0125    /// Construct an array of `nElements` container objects and return the base address of the array
0126    virtual void *NewArray(Int_t nElements) const { return !fClass.GetClass() ? nullptr : fClass->NewArray(nElements); }
0127    /// Construct an array of `nElements` container objects at the address given by `arena`
0128    virtual void *NewArray(Int_t nElements, void *arena) const
0129    {
0130       return !fClass.GetClass() ? nullptr : fClass->NewArray(nElements, arena);
0131    }
0132    /// Construct an array of `nElements` container objects and return the base address of the array
0133    virtual TClass::ObjectPtr NewObjectArray(Int_t nElements) const
0134    {
0135       return !fClass.GetClass() ? TClass::ObjectPtr{} : fClass->NewObjectArray(nElements);
0136    }
0137    /// Construct an array of `nElements` container objects at the address given by `arena`
0138    virtual TClass::ObjectPtr NewObjectArray(Int_t nElements, void *arena) const
0139    {
0140       return !fClass.GetClass() ? TClass::ObjectPtr{} : fClass->NewObjectArray(nElements, arena);
0141    }
0142 
0143    /// Execute the container destructor
0144    virtual void Destructor(void *p, Bool_t dtorOnly = kFALSE) const
0145    {
0146       TClass* cl = fClass.GetClass();
0147       if (cl) cl->Destructor(p, dtorOnly);
0148    }
0149 
0150    /// Execute the container array destructor
0151    virtual void DeleteArray(void *p, Bool_t dtorOnly = kFALSE) const
0152    {
0153       TClass* cl = fClass.GetClass();
0154       if (cl) cl->DeleteArray(p, dtorOnly);
0155    }
0156 
0157    /// Return the `sizeof()` of the collection object
0158    virtual UInt_t Sizeof() const = 0;
0159 
0160    /// Set the address of the container being proxied and keep track of the previous one
0161    virtual void PushProxy(void *objectstart) = 0;
0162 
0163    /// Reset the address of the container being proxied to the previous container
0164    virtual void PopProxy() = 0;
0165 
0166    /// Return `true` if the content is of type 'pointer to'
0167    virtual Bool_t HasPointers() const = 0;
0168 
0169    /// If the value type is a user-defined class, return a pointer to the `TClass` representing the
0170    /// value type of the container.
0171    virtual TClass *GetValueClass() const = 0;
0172 
0173    /// If the value type is a fundamental data type, return its type (see enumeration EDataType).
0174    virtual EDataType GetType() const = 0;
0175 
0176    /// Return the address of the value at index `idx`
0177    virtual void *At(UInt_t idx) = 0;
0178 
0179    /// Clear the container
0180    virtual void Clear(const char *opt = "") = 0;
0181 
0182    /// Return the current number of elements in the container
0183    virtual UInt_t Size() const = 0;
0184 
0185    /// Allocates space for storing at least `n` elements.  This function returns a pointer to the actual object on
0186    /// which insertions should take place.  For associative collections, this function returns a pointer to a temporary
0187    /// buffer known as the staging area.  If the insertion happened in a staging area (i.e. the returned pointer !=
0188    /// proxied object), `Commit()` should be called on the value returned by this function.
0189    virtual void*     Allocate(UInt_t n, Bool_t forceDelete) = 0;
0190 
0191    /// Commits pending elements in a staging area (see Allocate() for more information).
0192    virtual void      Commit(void*) = 0;
0193 
0194    /// Insert elements into the proxied container.  `data` is a C-style array of the value type of the given `size`.
0195    /// For associative containers, e.g. `std::map`, the data type should be `std::pair<Key_t, Value_t>`.
0196    virtual void Insert(const void *data, void *container, size_t size) = 0;
0197 
0198    /// Return the address of the value at index `idx`
0199    char *operator[](UInt_t idx) const { return (char *)(const_cast<TVirtualCollectionProxy *>(this))->At(idx); }
0200 
0201    // Functions related to member-wise actions
0202    virtual TStreamerInfoActions::TActionSequence *GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version) = 0;
0203    virtual TStreamerInfoActions::TActionSequence *GetReadMemberWiseActions(Int_t version) = 0;
0204    virtual TStreamerInfoActions::TActionSequence *GetWriteMemberWiseActions() = 0;
0205 
0206    /// The size of a small buffer that can be allocated on the stack to store iterator-specific information
0207    static const Int_t fgIteratorArenaSize = 16; // greater than sizeof(void*) + sizeof(UInt_t)
0208 
0209    /// `*begin_arena` and `*end_arena` should contain the location of a memory arena of size `fgIteratorArenaSize`.
0210    /// If iterator-specific information is of that size or less, the iterators will be constructed in place in the given
0211    /// locations.  Otherwise, iterators will be allocated via `new` and their address returned by modifying the value
0212    /// of `*begin_arena` and `*end_arena`.
0213    /// As a special case, given that iterators for array-backed containers are just pointers, the required information
0214    /// will be directly stored in `*(begin|end)_arena`.
0215    typedef void (*CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy);
0216 
0217    /// Return a pointer to a function that can create an iterator pair, where each iterator points to the begin and end
0218    /// of the collection, respectively (see CreateIterators_t).  If `read == kTRUE`, data is to be read from disk, i.e.
0219    /// written to the in-memory collection.
0220    virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read = kTRUE) = 0;
0221 
0222    /// Copy the iterator `source` into `dest`.  `dest` should contain the location of a memory arena of size
0223    /// `fgIteratorArenaSize`.
0224    /// If iterator-specific information is of that size or less, the iterators will be constructed in place in the given
0225    /// locations.  Otherwise, iterators will be allocated via `new` and their address returned by modifying the value
0226    /// of `*begin_arena` and `*end_arena`.  The actual address of the iterator is returned in any case.
0227    typedef void* (*CopyIterator_t)(void *dest, const void *source);
0228 
0229    /// Return a pointer to a function that can copy an iterator (see CopyIterator_t).  If `read == kTRUE`, data is to be
0230    /// read from disk, i.e. written to the in-memory collection.
0231    virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read = kTRUE) = 0;
0232 
0233    /// `iter` and `end` should be pointers to an iterator to be incremented and an iterator that points to the end of
0234    /// the collection, respectively.  If `iter` has not reached the end of the collection, this function increments the
0235    /// iterator and returns a pointer to the element before the increment.  Otherwise, `nullptr` is returned.
0236    typedef void* (*Next_t)(void *iter, const void *end);
0237 
0238    /// Return a pointer to a function that can advance an iterator (see Next_t).  If `read == kTRUE`, data is to be
0239    /// read from disk, i.e. written to the in-memory collection.
0240    virtual Next_t GetFunctionNext(Bool_t read = kTRUE) = 0;
0241 
0242    /// If the size of the iterator is greater than `fgIteratorArenaSize`, call delete on the addresses; otherwise, just
0243    /// call the iterator's destructor.
0244    typedef void (*DeleteIterator_t)(void *iter);
0245    typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
0246 
0247    /// Return a pointer to a function that can delete an iterator (pair) (see DeleteIterator_t).  If `read == kTRUE`,
0248    /// data is to be read from disk, i.e. written to the in-memory collection.
0249    virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read = kTRUE) = 0;
0250    virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read = kTRUE) = 0;
0251 };
0252 
0253 #endif