Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-24 09:25:14

0001 // @(#)root/io:$Id$
0002 // Author: Markus Frank  28/10/04
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
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 #ifndef ROOT_TGenCollectionProxy
0012 #define ROOT_TGenCollectionProxy
0013 
0014 #include "TBuffer.h"
0015 
0016 #include "TVirtualCollectionProxy.h"
0017 
0018 #include "TCollectionProxyInfo.h"
0019 
0020 #include "ROOT/RAlignmentUtils.hxx"
0021 
0022 #include <atomic>
0023 #include <string>
0024 #include <map>
0025 #include <cstdlib>
0026 #include <cstddef>
0027 #include <vector>
0028 #include <new>
0029 
0030 class TObjArray;
0031 class TCollectionProxyFactory;
0032 
0033 class TGenCollectionProxy
0034    : public TVirtualCollectionProxy
0035 {
0036 
0037    // Friend declaration
0038    friend class TCollectionProxyFactory;
0039 
0040 public:
0041 
0042 #ifdef R__HPUX
0043    typedef const std::type_info&      Info_t;
0044 #else
0045    typedef const std::type_info& Info_t;
0046 #endif
0047 
0048    enum {
0049       // Those 'bits' are used in conjunction with Cling's bit to store the 'type'
0050       // info into one int
0051       kBIT_ISSTRING   = 0x20000000,  // We can optimized a value operation when the content are strings
0052       kBIT_ISTSTRING  = 0x40000000
0053    };
0054 
0055    /** @class TGenCollectionProxy::Value TGenCollectionProxy.h TGenCollectionProxy.h
0056     *
0057     * Small helper to describe the Value_type or the key_type
0058     * of an STL container.
0059     *
0060     * @author  M.Frank
0061     * @version 1.0
0062     * @date    10/10/2004
0063     */
0064    struct Value  {
0065       ROOT::NewFunc_t fCtor;       ///< Method cache for containee constructor
0066       ROOT::DesFunc_t fDtor;       ///< Method cache for containee destructor
0067       ROOT::DelFunc_t fDelete;     ///< Method cache for containee delete
0068       UInt_t          fCase;       ///< type of data of Value_type
0069       UInt_t          fProperties; ///< Additional properties of the value type (kNeedDelete)
0070       TClassRef       fType;       ///< TClass reference of Value_type in collection
0071       EDataType       fKind;       ///< kind of ROOT-fundamental type
0072       size_t          fSize;       ///< fSize of the contained object
0073 
0074       // Default copy constructor has the correct implementation.
0075 
0076       // Initializing constructor
0077       Value(const std::string& info, Bool_t silent, size_t hint_pair_offset = 0, size_t hint_pair_size = 0);
0078       // Delete individual item from STL container
0079       void DeleteItem(void* ptr);
0080 
0081       Bool_t IsValid();
0082    };
0083 
0084    /**@class StreamHelper
0085     *
0086     * Helper class to facilitate I/O
0087     *
0088     * @author  M.Frank
0089     * @version 1.0
0090     * @date    10/10/2004
0091     */
0092    union StreamHelper  {
0093       Bool_t       boolean;
0094       Char_t       s_char;
0095       Short_t      s_short;
0096       Int_t        s_int;
0097       Long_t       s_long;
0098       Long64_t     s_longlong;
0099       Float_t      flt;
0100       Double_t     dbl;
0101       UChar_t      u_char;
0102       UShort_t     u_short;
0103       UInt_t       u_int;
0104       ULong_t      u_long;
0105       ULong64_t    u_longlong;
0106       void*        p_void;
0107       void**       pp_void;
0108       char*        kchar;
0109       TString*     tstr;
0110       void* ptr()  {
0111          return *(&this->p_void);
0112       }
0113       std::string* str()  {
0114          return (std::string*)this;
0115       }
0116       const char* c_str()  {
0117          return ((std::string*)this)->c_str();
0118       }
0119       const char* c_pstr()  {
0120          return (*(std::string**)this)->c_str();
0121       }
0122       void set(void* p)  {
0123          *(&this->p_void) = p;
0124       }
0125       void read_std_string(TBuffer& b) {
0126          TString s;
0127          s.Streamer(b);
0128          ((std::string*)this)->assign(s.Data());
0129       }
0130       void* read_tstring(TBuffer& b)  {
0131          *((TString*)this) = "";
0132          ((TString*)this)->Streamer(b);
0133          return this;
0134       }
0135       void read_std_string_pointer(TBuffer& b) {
0136          TString s;
0137          std::string* str2 = (std::string*)ptr();
0138          if (!str2) str2 = new std::string();
0139          s.Streamer(b);
0140          *str2 = s;
0141          set(str2);
0142       }
0143       void write_std_string_pointer(TBuffer& b)  {
0144          const char* c;
0145          if (ptr()) {
0146             std::string* strptr = (*(std::string**)this);
0147             c = (const char*)(strptr->c_str());
0148          } else c = "";
0149          TString(c).Streamer(b);
0150       }
0151       void read_any_object(Value* v, TBuffer& b)  {
0152          void* p = ptr();
0153          if ( p )  {
0154             if ( v->fDelete )  {    // Compiled content: call Destructor
0155                (*v->fDelete)(p);
0156             }
0157             else if ( v->fType )  { // Emulated content: call TClass::Delete
0158                v->fType->Destructor(p);
0159             }
0160             else if ( v->fDtor )  {
0161                (*v->fDtor)(p);
0162                ::operator delete(p);
0163             }
0164             else  {
0165                ::operator delete(p);
0166             }
0167          }
0168          set( b.ReadObjectAny(v->fType) );
0169       }
0170 
0171       void read_tstring_pointer(Bool_t vsn3, TBuffer& b)  {
0172          TString* s = (TString*)ptr();
0173          if ( vsn3 )  {
0174             if ( !s ) s = new TString();
0175             else s->Clear();
0176             s->Streamer(b);
0177             set(s);
0178             return;
0179          }
0180          if ( s ) delete s;
0181          set( b.ReadObjectAny(TString::Class()) );
0182       }
0183       void write_tstring_pointer(TBuffer& b)  {
0184          b.WriteObjectAny(ptr(), TString::Class());
0185       }
0186    };
0187 
0188    /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h
0189     *
0190     * Small helper to execute (compiler) generated function for the
0191     * access to STL or other containers.
0192     *
0193     * @author  M.Frank
0194     * @version 1.0
0195     * @date    10/10/2004
0196     */
0197    class Method  {
0198    public:
0199       typedef void* (*Call_t)(void*);
0200       Call_t call;
0201       Method() : call(nullptr)                 {      }
0202       Method(Call_t c) : call(c)               {      }
0203       Method(const Method& m) : call(m.call)   {      }
0204       Method &operator=(const Method& m) { call = m.call; return *this; }
0205       void* invoke(void* obj) const { return (*call)(obj); }
0206    };
0207 
0208    /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h
0209     *
0210     * Small helper to execute (compiler) generated function for the
0211     * access to STL or other containers.
0212     *
0213     * @author  M.Frank
0214     * @version 1.0
0215     * @date    10/10/2004
0216     */
0217    class Method0  {
0218    public:
0219       typedef void* (*Call_t)();
0220       Call_t call;
0221       Method0() : call(nullptr)                  {      }
0222       Method0(Call_t c) : call(c)                {      }
0223       Method0(const Method0& m) : call(m.call)   {      }
0224       Method0 &operator=(const Method0& m) { call = m.call; return *this; }
0225       void* invoke() const { return (*call)(); }
0226    };
0227 
0228    /** @class TGenCollectionProxy::TStaging
0229     *
0230     * Small helper to stage the content of an associative
0231     * container when reading and before inserting it in the
0232     * actual collection.
0233     *
0234     * @author  Ph.Canal
0235     * @version 1.0
0236     * @date    20/08/2010
0237     */
0238    class TStaging  {
0239       void   *fTarget;   ///< Pointer to the collection we are staging for.
0240       void   *fContent;  ///< Pointer to the content
0241       size_t  fReserved; ///< Amount of space already reserved.
0242       size_t  fSize;     ///< Number of elements
0243       size_t  fSizeOf;   ///< size of each elements
0244 
0245       TStaging(const TStaging&);            ///< Not implemented.
0246       TStaging &operator=(const TStaging&); ///< Not implemented.
0247 
0248    public:
0249       TStaging(size_t size, size_t size_of) : fTarget(nullptr), fContent(nullptr), fReserved(0), fSize(size), fSizeOf(size_of)
0250       {
0251          // Usual constructor.  Reserves the required number of elements.
0252          fReserved = fSize;
0253          fContent = ::malloc(fReserved * fSizeOf);
0254       }
0255 
0256       ~TStaging() {
0257          // Usual destructor
0258          ::free(fContent);
0259       }
0260 
0261       void   *GetContent() {
0262          // Return the location of the array of content.
0263          return fContent;
0264       }
0265       void   *GetEnd() {
0266          // Return the 'end' of the array of content.
0267          return ((char*)fContent) + fSize*fSizeOf;
0268       }
0269       size_t  GetSize() {
0270          // Return the number of elements.
0271          return fSize;
0272       }
0273       void   *GetTarget() {
0274          // Get the address of the collection we are staging for.
0275          return fTarget;
0276       }
0277       void    Resize(size_t nelement) {
0278          if (fReserved < nelement) {
0279             fReserved = nelement;
0280             fContent = ::realloc(fContent,fReserved * fSizeOf);
0281          }
0282          fSize = nelement;
0283       }
0284       void SetTarget(void *target) {
0285          // Set the collection we are staging for.
0286          fTarget = target;
0287       }
0288    };
0289 
0290 protected:
0291    typedef ROOT::Detail::TCollectionProxyInfo::Environ<char[64]> Env_t;
0292    typedef ROOT::Detail::TCollectionProxyInfo::EnvironBase EnvironBase_t;
0293    typedef std::vector<TStaging*>          Staged_t;  ///< Collection of pre-allocated staged array for associative containers.
0294    typedef std::vector<EnvironBase_t*>     Proxies_t;
0295    mutable TObjArray *fReadMemberWise;                                   ///< Array of bundle of TStreamerInfoActions to stream out (read)
0296    mutable std::map<std::string, TObjArray*> *fConversionReadMemberWise; ///< Array of bundle of TStreamerInfoActions to stream out (read) derived from another class.
0297    mutable TStreamerInfoActions::TActionSequence *fWriteMemberWise;
0298    typedef void (*Sizing_t)(void *obj, size_t size);
0299    typedef void* (*Feedfunc_t)(void *from, void *to, size_t size);
0300    typedef void* (*Collectfunc_t)(void *from, void *to);
0301    typedef void* (*ArrIterfunc_t)(void *from, size_t size);
0302 
0303    std::string   fName;      ///< Name of the class being proxied.
0304    Bool_t        fPointers;  ///< Flag to indicate if containee has pointers (key or value)
0305    Method        fClear;     ///< Method cache for container accessors: clear container
0306    Method        fSize;      ///< Container accessors: size of container
0307    Sizing_t      fResize;    ///< Container accessors: resize container
0308    Method        fFirst;     ///< Container accessors: generic iteration: first
0309    Method        fNext;      ///< Container accessors: generic iteration: next
0310    ArrIterfunc_t fConstruct; ///< Container accessors: block construct
0311    Sizing_t      fDestruct;  ///< Container accessors: block destruct
0312    Feedfunc_t    fFeed;      ///< Container accessors: block feed
0313    Collectfunc_t fCollect;   ///< Method to collect objects from container
0314    Method0       fCreateEnv; ///< Method to allocate an Environment holder.
0315    std::atomic<Value*> fValue;     ///< Descriptor of the container value type
0316    Value*        fVal;       ///< Descriptor of the Value_type
0317    Value*        fKey;       ///< Descriptor of the key_type
0318    EnvironBase_t*fEnv;       ///< Address of the currently proxied object
0319    int           fValOffset; ///< Offset from key to value (in maps)
0320    int           fValDiff;   ///< Offset between two consecutive value_types (memory layout).
0321    Proxies_t     fProxyList; ///< Stack of recursive proxies
0322    Proxies_t     fProxyKept; ///< Optimization: Keep proxies once they were created
0323    Staged_t      fStaged;    ///< Optimization: Keep staged array once they were created
0324    int           fSTL_type;  ///< STL container type
0325    Info_t        fTypeinfo;  ///< Type information
0326    TClass*       fOnFileClass; ///< On file class
0327 
0328    CreateIterators_t    fFunctionCreateIterators;
0329    CopyIterator_t       fFunctionCopyIterator;
0330    Next_t               fFunctionNextIterator;
0331    DeleteIterator_t     fFunctionDeleteIterator;
0332    DeleteTwoIterators_t fFunctionDeleteTwoIterators;
0333 
0334    // Late initialization of collection proxy
0335    TGenCollectionProxy* Initialize(Bool_t silent) const;
0336    // Some hack to avoid const-ness.
0337    virtual TGenCollectionProxy* InitializeEx(Bool_t silent);
0338    // Call to delete/destruct individual contained item.
0339    virtual void DeleteItem(Bool_t force, void* ptr) const;
0340    // Allow to check function pointers.
0341    void CheckFunctions()  const;
0342 
0343 private:
0344    TGenCollectionProxy(); // not implemented on purpose.
0345 
0346 public:
0347 
0348    // Virtual copy constructor.
0349    TVirtualCollectionProxy* Generate() const override;
0350 
0351    // Copy constructor.
0352    TGenCollectionProxy(const TGenCollectionProxy& copy);
0353 
0354 private:
0355    // Assignment operator
0356    TGenCollectionProxy &operator=(const TGenCollectionProxy&); // Not Implemented
0357 
0358 public:
0359    // Initializing constructor
0360    TGenCollectionProxy(Info_t typ, size_t iter_size);
0361    TGenCollectionProxy(const ROOT::Detail::TCollectionProxyInfo &info, TClass *cl);
0362 
0363    // Standard destructor.
0364    ~TGenCollectionProxy() override;
0365 
0366    // Reset the info gathered from StreamerInfos and value's TClass.
0367    Bool_t Reset() override;
0368 
0369    // Return a pointer to the TClass representing the container.
0370    TClass *GetCollectionClass() const override;
0371 
0372    // Return the type of collection see TClassEdit::ESTLType
0373    Int_t   GetCollectionType() const override;
0374 
0375    // Return the offset between two consecutive value_types (memory layout).
0376    ULong_t   GetIncrement() const override;
0377 
0378    // Return the sizeof the collection object.
0379    UInt_t Sizeof() const override;
0380 
0381    // Push new proxy environment.
0382    void PushProxy(void *objstart) override;
0383 
0384    // Pop old proxy environment.
0385    void PopProxy() override;
0386 
0387    // Return true if the content is of type 'pointer to'.
0388    Bool_t HasPointers() const override;
0389 
0390    // Return a pointer to the TClass representing the content.
0391    TClass *GetValueClass() const override;
0392 
0393    // If the content is a simple numerical value, return its type (see TDataType).
0394    EDataType GetType() const override;
0395 
0396    // Return the address of the value at index 'idx'.
0397    void *At(UInt_t idx) override;
0398 
0399    // Clear the container.
0400    void Clear(const char *opt = "") override;
0401 
0402    // Resize the container.
0403    virtual void Resize(UInt_t n, Bool_t force_delete);
0404 
0405    // Return the current size of the container.
0406    UInt_t Size() const override;
0407 
0408    // Block allocation of containees.
0409    void* Allocate(UInt_t n, Bool_t forceDelete) override;
0410 
0411    // Insert data into the container where data is a C-style array of the actual type contained in the collection
0412    // of the given size.   For associative container (map, etc.), the data type is the pair<key,value>.
0413    void  Insert(const void *data, void *container, size_t size) override;
0414 
0415    // Block commit of containees.
0416    void Commit(void* env) override;
0417 
0418    // Streamer function.
0419    virtual void Streamer(TBuffer &refBuffer);
0420 
0421    // Streamer I/O overload.
0422    virtual void Streamer(TBuffer &refBuffer, void *pObject, int siz);
0423 
0424    // TClassStreamer I/O overload.
0425    virtual void operator()(TBuffer &refBuffer, void *pObject);
0426 
0427    // Routine to read the content of the buffer into 'obj'.
0428    virtual void ReadBuffer(TBuffer &b, void *obj);
0429    virtual void ReadBuffer(TBuffer &b, void *obj, const TClass *onfileClass);
0430 
0431    virtual void SetOnFileClass( TClass* cl ) { fOnFileClass = cl; }
0432    virtual TClass* GetOnFileClass() const { return fOnFileClass; }
0433 
0434    // MemberWise actions
0435    TStreamerInfoActions::TActionSequence *GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version) override;
0436    TStreamerInfoActions::TActionSequence *GetReadMemberWiseActions(Int_t version) override;
0437    TStreamerInfoActions::TActionSequence *GetWriteMemberWiseActions() override;
0438 
0439    // Set of functions to iterate easily through the collection
0440 
0441    CreateIterators_t GetFunctionCreateIterators(Bool_t read = kTRUE) override;
0442    // typedef void (*CreateIterators_t)(void *collection, void **begin_arena, void **end_arena);
0443    // begin_arena and end_arena should contain the location of a memory arena of size fgIteratorSize.
0444    // If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
0445    // Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
0446 
0447    CopyIterator_t GetFunctionCopyIterator(Bool_t read = kTRUE) override;
0448    // typedef void* (*CopyIterator_t)(void **dest, const void *source);
0449    // Copy the iterator source, into dest.   dest should contain the location of a memory arena of size fgIteratorSize.
0450    // If the collection iterator is of that size or less, the iterator will be constructed in place in this location (new with placement)
0451    // Otherwise the iterator will be allocated via a regular new.
0452    // The actual address of the iterator is returned in both case.
0453 
0454    Next_t GetFunctionNext(Bool_t read = kTRUE) override;
0455    // typedef void* (*Next_t)(void *iter, const void *end);
0456    // iter and end should be pointers to respectively an iterator to be incremented and the result of collection.end()
0457    // If the iterator has not reached the end of the collection, 'Next' increment the iterator 'iter' and return 0 if
0458    // the iterator reached the end.
0459    // If the end was not reached, 'Next' returns the address of the content pointed to by the iterator before the
0460    // incrementation ; if the collection contains pointers, 'Next' will return the value of the pointer.
0461 
0462    DeleteIterator_t GetFunctionDeleteIterator(Bool_t read = kTRUE) override;
0463    DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read = kTRUE) override;
0464    // typedef void (*DeleteIterator_t)(void *iter);
0465    // typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
0466    // If the size of the iterator is greater than fgIteratorArenaSize, call delete on the addresses,
0467    // Otherwise just call the iterator's destructor.
0468 
0469 };
0470 
0471 template <typename T>
0472 struct AnyCollectionProxy : public TGenCollectionProxy  {
0473    AnyCollectionProxy()
0474       : TGenCollectionProxy(typeid(T::Cont_t),sizeof(T::Iter_t))
0475    {
0476       // Constructor.
0477       fValDiff        = sizeof(T::Value_t);
0478       fValOffset      = T::value_offset();
0479       fSize.call      = T::size;
0480       fResize         = T::resize;
0481       fNext.call      = T::next;
0482       fFirst.call     = T::first;
0483       fClear.call     = T::clear;
0484       fConstruct      = T::construct;
0485       fDestruct       = T::destruct;
0486       fFeed           = T::feed;
0487       CheckFunctions();
0488    }
0489    ~AnyCollectionProxy() override {  }
0490 };
0491 
0492 #endif
0493