Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:11:36

0001 // @(#)root/cont:$Id$
0002 // Author: Markus Frank  28/10/04. Philippe Canal 02/01/2007
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 
0012 #ifndef ROOT_TCollectionProxyInfo
0013 #define ROOT_TCollectionProxyInfo
0014 
0015 //////////////////////////////////////////////////////////////////////////
0016 //                                                                      //
0017 //  Small helper to gather the information neede to generate a          //
0018 //  Collection Proxy                                                    //
0019 //
0020 //////////////////////////////////////////////////////////////////////////
0021 
0022 #include "RtypesCore.h"
0023 #include "TError.h"
0024 #include <vector>
0025 #include <forward_list>
0026 #include <utility>
0027 
0028 #if defined(_WIN32)
0029    #if _MSC_VER<1300
0030       #define TYPENAME
0031       #define R__VCXX6
0032    #else
0033       #define TYPENAME typename
0034    #endif
0035 #else
0036    #define TYPENAME typename
0037 #endif
0038 
0039 class TVirtualCollectionProxy;
0040 
0041 namespace ROOT {
0042 namespace VecOps {
0043 template <typename T>
0044 class RVec;
0045 }
0046 
0047 namespace Internal {
0048 template <typename T> class TStdBitsetHelper {
0049    // This class is intentionally empty, this is scaffolding to allow the equivalent
0050    // of 'template <int N> struct TCollectionProxyInfo::Type<std::bitset<N> >' which
0051    // is not effective in C++ (as of gcc 4.3.3).
0052 };
0053 }
0054 
0055 namespace Detail {
0056 
0057    class TCollectionProxyInfo {
0058       // This class is a place holder for the information needed
0059       // to create the proper Collection Proxy.
0060       // This is similar to Reflex's CollFuncTable.
0061 
0062    public:
0063 
0064       // Same value as TVirtualCollectionProxy.
0065       static const UInt_t fgIteratorArenaSize = 16; // greater than sizeof(void*) + sizeof(UInt_t)
0066 
0067    /** @class ROOT::Detail::TCollectionProxyInfo::IteratorValue
0068     *
0069     * Small helper to encapsulate whether to return the value
0070     * pointed to by the iterator or its address.
0071     *
0072     **/
0073 
0074       template <typename Cont_t, typename value> struct IteratorValue {
0075          static void* get(typename Cont_t::iterator &iter) {
0076             return (void*)&(*iter);
0077          }
0078       };
0079 
0080       template <typename Cont_t, typename value_ptr> struct IteratorValue<Cont_t, value_ptr*> {
0081          static void* get(typename Cont_t::iterator &iter) {
0082             return (void*)(*iter);
0083          }
0084       };
0085 
0086    /** @class ROOT::Detail::TCollectionProxyInfo::Iterators
0087     *
0088     * Small helper to implement the function to create,access and destroy
0089     * iterators.
0090     *
0091     **/
0092 
0093       template <typename Cont_t, bool large = false>
0094       struct Iterators {
0095          typedef Cont_t *PCont_t;
0096          typedef typename Cont_t::iterator iterator;
0097 
0098          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0099             PCont_t c = PCont_t(coll);
0100             new (*begin_arena) iterator(c->begin());
0101             new (*end_arena) iterator(c->end());
0102          }
0103          static void* copy(void *dest_arena, const void *source_ptr) {
0104             iterator *source = (iterator *)(source_ptr);
0105             new (dest_arena) iterator(*source);
0106             return dest_arena;
0107          }
0108          static void* next(void *iter_loc, const void *end_loc) {
0109             iterator *end = (iterator *)(end_loc);
0110             iterator *iter = (iterator *)(iter_loc);
0111             if (*iter != *end) {
0112                void *result = IteratorValue<Cont_t, typename Cont_t::value_type>::get(*iter);
0113                ++(*iter);
0114                return result;
0115             }
0116             return nullptr;
0117          }
0118          static void destruct1(void *iter_ptr) {
0119             iterator *start = (iterator *)(iter_ptr);
0120             start->~iterator();
0121          }
0122          static void destruct2(void *begin_ptr, void *end_ptr) {
0123             iterator *start = (iterator *)(begin_ptr);
0124             iterator *end = (iterator *)(end_ptr);
0125             start->~iterator();
0126             end->~iterator();
0127          }
0128       };
0129 
0130       // For Vector we take an extra short cut to avoid derefencing
0131       // the iterator all the time and redefine the 'address' of the
0132       // iterator as the iterator itself.  This requires special handling
0133       // in the looper (see TStreamerInfoAction) but is much faster.
0134       template <typename T> struct Iterators<std::vector<T>, false> {
0135          typedef std::vector<T> Cont_t;
0136          typedef Cont_t *PCont_t;
0137          typedef typename Cont_t::iterator iterator;
0138 
0139          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0140             PCont_t c = PCont_t(coll);
0141             if (c->empty()) {
0142                *begin_arena = nullptr;
0143                *end_arena = nullptr;
0144                return;
0145             }
0146             *begin_arena = &(*c->begin());
0147 #ifdef R__VISUAL_CPLUSPLUS
0148             *end_arena = &(*(c->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
0149 #else
0150             // coverity[past_the_end] Safe on other platforms
0151             *end_arena = &(*c->end());
0152 #endif
0153          }
0154          static void* copy(void *dest, const void *source) {
0155             *(void**)dest = *(void**)(const_cast<void*>(source));
0156             return dest;
0157          }
0158          static void* next(void * /* iter_loc */, const void * /* end_loc */) {
0159             // Should not be used.
0160             // In the case of vector, so that the I/O can perform better,
0161             // the begin_arena and the end_arena are *not* set to the
0162             // address of any iterator rather they are set to the value of
0163             // the beginning (and end) address of the vector's data.
0164             // Hence this routine (which takes the value of fBegin) can
0165             // *not* update where its points to (which in the case of vector
0166             // would require update the value of fBegin).
0167             R__ASSERT(0 && "Intentionally not implemented, do not use.");
0168             return nullptr;
0169          }
0170          static void destruct1(void  * /* iter_ptr */) {
0171             // Nothing to do
0172          }
0173          static void destruct2(void * /* begin_ptr */, void * /* end_ptr */) {
0174             // Nothing to do
0175          }
0176       };
0177 
0178       template <typename Cont_t> struct Iterators<Cont_t, /* large= */ true > {
0179          typedef Cont_t *PCont_t;
0180          typedef typename Cont_t::iterator iterator;
0181 
0182          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0183             PCont_t  c = PCont_t(coll);
0184             *begin_arena = new iterator(c->begin());
0185             *end_arena = new iterator(c->end());
0186          }
0187          static void* copy(void * /*dest_arena*/, const void *source_ptr) {
0188             iterator *source = (iterator *)(source_ptr);
0189             void *iter = new iterator(*source);
0190             return iter;
0191          }
0192          static void* next(void *iter_loc, const void *end_loc) {
0193             iterator *end = (iterator *)(end_loc);
0194             iterator *iter = (iterator *)(iter_loc);
0195             if (*iter != *end) {
0196                void *result = IteratorValue<Cont_t, typename Cont_t::value_type>::get(*iter);
0197                ++(*iter);
0198                return result;
0199             }
0200             return nullptr;
0201          }
0202          static void destruct1(void *begin_ptr) {
0203             iterator *start = (iterator *)(begin_ptr);
0204             delete start;
0205          }
0206          static void destruct2(void *begin_ptr, void *end_ptr) {
0207             iterator *start = (iterator *)(begin_ptr);
0208             iterator *end = (iterator *)(end_ptr);
0209             delete start;
0210             delete end;
0211          }
0212       };
0213 
0214   /** @class ROOT::Detail::TCollectionProxyInfo::Environ
0215     *
0216     * Small helper to save proxy environment in the event of
0217     * recursive calls.
0218     *
0219     * @author  M.Frank
0220     * @version 1.0
0221     * @date    10/10/2004
0222     */
0223    struct EnvironBase {
0224    private:
0225       EnvironBase(const EnvironBase&); // Intentionally not implement, copy is not supported
0226       EnvironBase &operator=(const EnvironBase&); // Intentionally not implement, copy is not supported
0227    public:
0228       EnvironBase() : fIdx(0), fSize(0), fObject(nullptr), fStart(nullptr), fTemp(nullptr), fUseTemp(kFALSE), fRefCount(1), fSpace(0)
0229       {
0230       }
0231       virtual ~EnvironBase() {}
0232       size_t              fIdx;
0233       size_t              fSize;
0234       void*               fObject;
0235       void*               fStart;
0236       void*               fTemp;
0237       union {
0238          Bool_t fUseTemp;
0239          Bool_t fLastValueVecBool;
0240       };
0241       int                 fRefCount;
0242       size_t              fSpace;
0243    };
0244    template <typename T> struct Environ : public EnvironBase {
0245       Environ() : fIterator() {}
0246       typedef T           Iter_t;
0247       Iter_t              fIterator;
0248       T& iter() { return fIterator; }
0249       static void        *Create() {
0250          return new Environ();
0251       }
0252    };
0253 
0254    template <class T, class Q> struct PairHolder {
0255       T first;
0256       Q second;
0257       PairHolder() {}
0258       PairHolder(const PairHolder& c) : first(c.first), second(c.second) {}
0259       virtual ~PairHolder() {}
0260    private:
0261       PairHolder& operator=(const PairHolder&) = delete;
0262    };
0263 
0264    template <class T> struct Address {
0265       virtual ~Address() {}
0266       static void* address(T ref) {
0267          return const_cast<void*>(reinterpret_cast<const void*>(&ref));
0268       }
0269    };
0270 
0271    struct SfinaeHelper {
0272       // Use SFINAE to get the size of the container
0273 
0274       // In general we get the size of the container with the size method
0275       template <class T>
0276       static size_t GetContainerSize(const T& c) {return c.size();}
0277 
0278       // Since forward_list does not provide a size operator, we have to
0279       // use an alternative. This has a cost of course.
0280       template <class T, class ALLOCATOR>
0281       static size_t GetContainerSize(const std::forward_list<T,ALLOCATOR>& c) {return std::distance(c.begin(),c.end());}
0282    };
0283 
0284    /** @class ROOT::Detail::TCollectionProxyInfo::Type
0285     *
0286     * Small helper to encapsulate basic data accesses for
0287     * all STL continers.
0288     *
0289     * @author  M.Frank
0290     * @version 1.0
0291     * @date    10/10/2004
0292     */
0293    template <class T> struct Type
0294       : public Address<TYPENAME T::const_reference>
0295    {
0296       typedef T                      Cont_t;
0297       typedef typename T::iterator   Iter_t;
0298       typedef typename T::value_type Value_t;
0299       typedef Environ<Iter_t>        Env_t;
0300       typedef Env_t                 *PEnv_t;
0301       typedef Cont_t                *PCont_t;
0302       typedef Value_t               *PValue_t;
0303 
0304       virtual ~Type() {}
0305 
0306       static inline PCont_t object(void* ptr)   {
0307          return PCont_t(PEnv_t(ptr)->fObject);
0308       }
0309       static void* size(void* env)  {
0310          PEnv_t  e = PEnv_t(env);
0311          e->fSize   = SfinaeHelper::GetContainerSize(*PCont_t(e->fObject));
0312          return &e->fSize;
0313       }
0314       static void* clear(void* env)  {
0315          object(env)->clear();
0316          return nullptr;
0317       }
0318       static void* first(void* env)  {
0319          PEnv_t  e = PEnv_t(env);
0320          PCont_t c = PCont_t(e->fObject);
0321 #if 0
0322          // Assume iterators do not need destruction
0323          ::new(e->buff) Iter_t(c->begin());
0324 #endif
0325          e->fIterator = c->begin();
0326          e->fSize  = SfinaeHelper::GetContainerSize(*c);
0327          if ( 0 == e->fSize ) return e->fStart = nullptr;
0328          TYPENAME T::const_reference ref = *(e->iter());
0329          return e->fStart = Type<T>::address(ref);
0330       }
0331       static void* next(void* env)  {
0332          PEnv_t  e = PEnv_t(env);
0333          PCont_t c = PCont_t(e->fObject);
0334          for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
0335          // TODO: Need to find something for going backwards....
0336          if ( e->iter() == c->end() ) return nullptr;
0337          TYPENAME T::const_reference ref = *(e->iter());
0338          return Type<T>::address(ref);
0339       }
0340       static void* construct(void *what, size_t size)  {
0341          PValue_t m = PValue_t(what);
0342          for (size_t i=0; i<size; ++i, ++m)
0343             ::new(m) Value_t();
0344          return nullptr;
0345       }
0346       static void* collect(void *coll, void *array)  {
0347          PCont_t  c = PCont_t(coll);
0348          PValue_t m = PValue_t(array);
0349          for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
0350             ::new(m) Value_t(*i);
0351          return nullptr;
0352       }
0353       static void destruct(void *what, size_t size)  {
0354          PValue_t m = PValue_t(what);
0355          for (size_t i=0; i < size; ++i, ++m )
0356             m->~Value_t();
0357       }
0358 
0359       static const bool fgLargeIterator = sizeof(typename Cont_t::iterator) > fgIteratorArenaSize;
0360       typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
0361 
0362    };
0363 
0364    /** @class ROOT::Detail::TCollectionProxyInfo::Pushback
0365     *
0366     * Small helper to encapsulate all necessary data accesses for
0367     * containers like vector, list, deque
0368     *
0369     * @author  M.Frank
0370     * @version 1.0
0371     * @date    10/10/2004
0372     */
0373    template <class T> struct Pushback : public Type<T> {
0374       typedef T                      Cont_t;
0375       typedef typename T::iterator   Iter_t;
0376       typedef typename T::value_type Value_t;
0377       typedef Environ<Iter_t>        Env_t;
0378       typedef Env_t                 *PEnv_t;
0379       typedef Cont_t                *PCont_t;
0380       typedef Value_t               *PValue_t;
0381       static void resize(void* obj, size_t n) {
0382          PCont_t c = PCont_t(obj);
0383          c->resize(n);
0384       }
0385       static void* feed(void *from, void *to, size_t size)  {
0386          PCont_t  c = PCont_t(to);
0387          PValue_t m = PValue_t(from);
0388          for (size_t i=0; i<size; ++i, ++m)
0389             c->push_back(*m);
0390          return nullptr;
0391       }
0392       static int value_offset()  {
0393          return 0;
0394       }
0395    };
0396 
0397    /** @class ROOT::Detail::TCollectionProxyInfo::Pushfront
0398     *
0399     * Small helper to encapsulate all necessary data accesses for
0400     * containers like forward_list
0401     *
0402     * @author  D.Piparo
0403     * @version 1.0
0404     * @date    26/02/2015
0405     */
0406    template <class T> struct Pushfront : public Type<T> {
0407       typedef T                      Cont_t;
0408       typedef typename T::iterator   Iter_t;
0409       typedef typename T::value_type Value_t;
0410       typedef Environ<Iter_t>        Env_t;
0411       typedef Env_t                 *PEnv_t;
0412       typedef Cont_t                *PCont_t;
0413       typedef Value_t               *PValue_t;
0414       static void resize(void* obj, size_t n) {
0415          PCont_t c = PCont_t(obj);
0416          c->resize(n);
0417       }
0418       static void* feed(void *from, void *to, size_t size)  {
0419          PCont_t  c = PCont_t(to);
0420          if (size==0) return nullptr;
0421          PValue_t m = &(PValue_t(from)[size-1]); // Take the last item
0422          // Iterate backwards not to revert ordering
0423          for (size_t i=0; i<size; ++i, --m){
0424             c->push_front(*m);
0425          }
0426          return nullptr;
0427       }
0428       static int value_offset()  {
0429          return 0;
0430       }
0431    };
0432 
0433    /** @class ROOT::Detail::TCollectionProxyInfo::Insert
0434     *
0435     * Small helper to encapsulate all necessary data accesses for
0436     * containers like set, multiset etc.
0437     *
0438     * @author  M.Frank
0439     * @version 1.0
0440     * @date    10/10/2004
0441     */
0442    template <class T> struct Insert : public Type<T> {
0443       typedef T                      Cont_t;
0444       typedef typename T::iterator   Iter_t;
0445       typedef typename T::value_type Value_t;
0446       typedef Environ<Iter_t>        Env_t;
0447       typedef Env_t                 *PEnv_t;
0448       typedef Cont_t                *PCont_t;
0449       typedef Value_t               *PValue_t;
0450       static void* feed(void *from, void *to, size_t size)  {
0451          PCont_t  c = PCont_t(to);
0452          PValue_t m = PValue_t(from);
0453          for (size_t i=0; i<size; ++i, ++m)
0454             c->insert(*m);
0455          return nullptr;
0456       }
0457       static void resize(void* /* obj */, size_t )  {
0458          ;
0459       }
0460       static int value_offset()  {
0461          return 0;
0462       }
0463    };
0464 
0465    /** @class ROOT::Detail::TCollectionProxyInfo::MapInsert
0466     *
0467     * Small helper to encapsulate all necessary data accesses for
0468     * containers like set, multiset etc.
0469     *
0470     * @author  M.Frank
0471     * @version 1.0
0472     * @date    10/10/2004
0473     */
0474    template <class T> struct MapInsert : public Type<T> {
0475       typedef T                      Cont_t;
0476       typedef typename T::iterator   Iter_t;
0477       typedef typename T::value_type Value_t;
0478       typedef Environ<Iter_t>        Env_t;
0479       typedef Env_t                 *PEnv_t;
0480       typedef Cont_t                *PCont_t;
0481       typedef Value_t               *PValue_t;
0482       static void* feed(void *from, void *to, size_t size)  {
0483          PCont_t  c = PCont_t(to);
0484          PValue_t m = PValue_t(from);
0485          for (size_t i=0; i<size; ++i, ++m)
0486             c->insert(*m);
0487          return nullptr;
0488       }
0489       static void resize(void* /* obj */, size_t )  {
0490          ;
0491       }
0492       static int value_offset()  {
0493          return ((char*)&((PValue_t(0x1000))->second)) - ((char*)PValue_t(0x1000));
0494       }
0495    };
0496 
0497 
0498    public:
0499       const std::type_info &fInfo;
0500       size_t fIterSize;
0501       size_t fValueDiff;
0502       int    fValueOffset;
0503       void*  (*fSizeFunc)(void*);
0504       void   (*fResizeFunc)(void*,size_t);
0505       void*  (*fClearFunc)(void*);
0506       void*  (*fFirstFunc)(void*);
0507       void*  (*fNextFunc)(void*);
0508       void*  (*fConstructFunc)(void*,size_t);
0509       void   (*fDestructFunc)(void*,size_t);
0510       void*  (*fFeedFunc)(void*,void*,size_t);
0511       void*  (*fCollectFunc)(void*,void*);
0512       void*  (*fCreateEnv)();
0513 
0514       // Set of function of direct iteration of the collections.
0515       void (*fCreateIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy);
0516       // begin_arena and end_arena should contain the location of memory arena  of size fgIteratorSize.
0517       // If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
0518       // Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
0519 
0520       void* (*fCopyIterator)(void *dest, const void *source);
0521       // Copy the iterator source, into dest.   dest should contain should contain the location of memory arena  of size fgIteratorSize.
0522       // If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
0523       // Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
0524 
0525       void* (*fNext)(void *iter, const void *end);
0526       // iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
0527       // 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
0528       // If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
0529       // which case 'Next' will return the value of the pointer.
0530 
0531       void (*fDeleteSingleIterator)(void *iter);
0532       void (*fDeleteTwoIterators)(void *begin, void *end);
0533       // If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
0534       // Otherwise just call the iterator's destructor.
0535 
0536    public:
0537       TCollectionProxyInfo(const std::type_info& info,
0538                            size_t iter_size,
0539                            size_t value_diff,
0540                            int    value_offset,
0541                            void*  (*size_func)(void*),
0542                            void   (*resize_func)(void*,size_t),
0543                            void*  (*clear_func)(void*),
0544                            void*  (*first_func)(void*),
0545                            void*  (*next_func)(void*),
0546                            void*  (*construct_func)(void*,size_t),
0547                            void   (*destruct_func)(void*,size_t),
0548                            void*  (*feed_func)(void*,void*,size_t),
0549                            void*  (*collect_func)(void*,void*),
0550                            void*  (*create_env)(),
0551                            void   (*getIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy) = nullptr,
0552                            void*  (*copyIterator)(void *dest, const void *source) = nullptr,
0553                            void*  (*next)(void *iter, const void *end) = nullptr,
0554                            void   (*deleteSingleIterator)(void *iter) = nullptr,
0555                            void   (*deleteTwoIterators)(void *begin, void *end) = nullptr
0556                            ) :
0557          fInfo(info), fIterSize(iter_size), fValueDiff(value_diff),
0558          fValueOffset(value_offset),
0559          fSizeFunc(size_func),fResizeFunc(resize_func),fClearFunc(clear_func),
0560          fFirstFunc(first_func),fNextFunc(next_func),fConstructFunc(construct_func),
0561          fDestructFunc(destruct_func),fFeedFunc(feed_func),fCollectFunc(collect_func),
0562          fCreateEnv(create_env),
0563          fCreateIterators(getIterators),fCopyIterator(copyIterator),fNext(next),
0564          fDeleteSingleIterator(deleteSingleIterator),fDeleteTwoIterators(deleteTwoIterators)
0565       {
0566       }
0567 
0568       /// Generate proxy from template
0569       template <class T> static TCollectionProxyInfo* Generate(const T&)  {
0570          // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
0571          // template (used to described the behavior of the stl collection.
0572          // Typical use looks like:
0573          //      ::ROOT::Detail::TCollectionProxyInfo::Generate(TCollectionProxyInfo::Pushback< std::vector<string> >()));
0574 
0575          PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
0576             (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
0577          return new TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
0578                                                sizeof(TYPENAME T::Iter_t),
0579                                                (((char*)&p->second)-((char*)&p->first)),
0580                                                T::value_offset(),
0581                                                T::size,
0582                                                T::resize,
0583                                                T::clear,
0584                                                T::first,
0585                                                T::next,
0586                                                T::construct,
0587                                                T::destruct,
0588                                                T::feed,
0589                                                T::collect,
0590                                                T::Env_t::Create,
0591                                                T::Iterators_t::create,
0592                                                T::Iterators_t::copy,
0593                                                T::Iterators_t::next,
0594                                                T::Iterators_t::destruct1,
0595                                                T::Iterators_t::destruct2);
0596       }
0597 
0598       template <class T> static TCollectionProxyInfo Get(const T&)  {
0599 
0600          // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
0601          // template (used to described the behavior of the stl collection.
0602          // Typical use looks like:
0603          //      ::ROOT::Detail::TCollectionProxyInfo::Get(TCollectionProxyInfo::Pushback< std::vector<string> >()));
0604 
0605          PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
0606             (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
0607          return TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
0608                                            sizeof(TYPENAME T::Iter_t),
0609                                            (((char*)&p->second)-((char*)&p->first)),
0610                                            T::value_offset(),
0611                                            T::size,
0612                                            T::resize,
0613                                            T::clear,
0614                                            T::first,
0615                                            T::next,
0616                                            T::construct,
0617                                            T::destruct,
0618                                            T::feed,
0619                                            T::collect,
0620                                            T::Env_t::Create);
0621       }
0622 
0623    };
0624 
0625    // This specialization is chosen if T is a vector<bool, A>, irrespective of the nature
0626    // of the allocator A represents.
0627    template <class A> struct TCollectionProxyInfo::Type<std::vector<Bool_t, A>>
0628    : public TCollectionProxyInfo::Address<typename std::vector<Bool_t, A>::const_reference>
0629    {
0630       typedef std::vector<Bool_t, A>       Cont_t;
0631       typedef typename Cont_t::iterator    Iter_t;
0632       typedef typename Cont_t::value_type  Value_t;
0633       typedef Environ<Iter_t>              Env_t;
0634       typedef Env_t                       *PEnv_t;
0635       typedef Cont_t                      *PCont_t;
0636       typedef Value_t                     *PValue_t;
0637 
0638       virtual ~Type() {}
0639 
0640       static inline PCont_t object(void* ptr)   {
0641          return PCont_t(PEnv_t(ptr)->fObject);
0642       }
0643       static void* size(void* env)  {
0644          PEnv_t  e = PEnv_t(env);
0645          e->fSize   = PCont_t(e->fObject)->size();
0646          return &e->fSize;
0647       }
0648       static void* clear(void* env)  {
0649          object(env)->clear();
0650          return nullptr;
0651       }
0652       static void* first(void* env)  {
0653          PEnv_t  e = PEnv_t(env);
0654          PCont_t c = PCont_t(e->fObject);
0655 #if 0
0656          // Assume iterators do not need destruction
0657          ::new(e->buff) Iter_t(c->begin());
0658 #endif
0659          e->fIterator = c->begin();
0660          e->fSize  = c->size();
0661          return nullptr;
0662       }
0663       static void* next(void* env)  {
0664          PEnv_t  e = PEnv_t(env);
0665          PCont_t c = PCont_t(e->fObject);
0666          for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
0667          // TODO: Need to find something for going backwards....
0668          return nullptr;
0669       }
0670       static void* construct(void*,size_t)  {
0671          // Nothing to construct.
0672          return nullptr;
0673       }
0674       static void* collect(void *coll, void *array)  {
0675          PCont_t  c = PCont_t(coll);
0676          PValue_t m = PValue_t(array); // 'start' is a buffer outside the container.
0677          for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
0678             ::new(m) Value_t(*i);
0679          return nullptr;
0680       }
0681       static void destruct(void*,size_t)  {
0682          // Nothing to destruct.
0683       }
0684 
0685       //static const bool fgLargeIterator = sizeof(Cont_t::iterator) > fgIteratorArenaSize;
0686       //typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
0687 
0688       struct Iterators {
0689          typedef typename Cont_t::iterator iterator;
0690 
0691          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0692             PCont_t c = PCont_t(coll);
0693             new (*begin_arena) iterator(c->begin());
0694             new (*end_arena) iterator(c->end());
0695          }
0696          static void* copy(void *dest_arena, const void *source_ptr) {
0697             const iterator *source = (const iterator *)(source_ptr);
0698             new (dest_arena) iterator(*source);
0699             return dest_arena;
0700          }
0701          static void* next(void *, const void *) {
0702             R__ASSERT(false && "Intentionally not implemented, should use VectorLooper or similar for vector<bool>.");
0703             return {};
0704          }
0705          static void destruct1(void *iter_ptr) {
0706             iterator *start = (iterator *)(iter_ptr);
0707             start->~iterator();
0708          }
0709          static void destruct2(void *begin_ptr, void *end_ptr) {
0710             iterator *start = (iterator *)(begin_ptr);
0711             iterator *end = (iterator *)(end_ptr);
0712             start->~iterator();
0713             end->~iterator();
0714          }
0715       };
0716       typedef Iterators Iterators_t;
0717 
0718    };
0719 
0720    template <class A> struct TCollectionProxyInfo::Pushback<std::vector<Bool_t, A> > : public TCollectionProxyInfo::Type<std::vector<Bool_t, A> > {
0721       typedef std::vector<Bool_t, A>       Cont_t;
0722       typedef typename Cont_t::iterator    Iter_t;
0723       typedef typename Cont_t::value_type  Value_t;
0724       typedef Environ<Iter_t>              Env_t;
0725       typedef Env_t                       *PEnv_t;
0726       typedef Cont_t                      *PCont_t;
0727       typedef Value_t                     *PValue_t;
0728 
0729       static void resize(void* obj,size_t n) {
0730          PCont_t c = PCont_t(obj);
0731          c->resize(n);
0732       }
0733       static void* feed(void* from, void *to, size_t size)  {
0734          PCont_t  c = PCont_t(to);
0735          PValue_t m = PValue_t(from);
0736          for (size_t i=0; i<size; ++i, ++m)
0737             c->push_back(*m);
0738          return nullptr;
0739       }
0740       static int value_offset()  {
0741          return 0;
0742       }
0743    };
0744 
0745    // Need specialization for boolean references due to stupid STL std::vector<bool>
0746    template <class A> struct TCollectionProxyInfo::Address<std::vector<Bool_t, A>> {
0747       virtual ~Address() {}
0748       static void* address(typename std::vector<Bool_t, A>::const_reference) {
0749          R__ASSERT(false && "Intentionally not implemented, should use VectorLooper or other functions specialized for "
0750                             "vector<bool> instead");
0751          return {};
0752       }
0753    };
0754 
0755    template <typename Bitset_t> struct TCollectionProxyInfo::Type<Internal::TStdBitsetHelper<Bitset_t> > : public TCollectionProxyInfo::Address<const Bool_t &>
0756    {
0757       typedef Bitset_t                 Cont_t;
0758       typedef std::pair<size_t,Bool_t> Iter_t;
0759       typedef Bool_t                   Value_t;
0760       typedef Environ<Iter_t>          Env_t;
0761       typedef Env_t                   *PEnv_t;
0762       typedef Cont_t                  *PCont_t;
0763       typedef Value_t                 *PValue_t;
0764 
0765       virtual ~Type() {}
0766 
0767       static inline PCont_t object(void* ptr)   {
0768          return PCont_t(PEnv_t(ptr)->fObject);
0769       }
0770       static void* size(void* env)  {
0771          PEnv_t  e = PEnv_t(env);
0772          e->fSize   = PCont_t(e->fObject)->size();
0773          return &e->fSize;
0774       }
0775       static void* clear(void* env)  {
0776          object(env)->reset();
0777          return nullptr;
0778       }
0779       static void* first(void* env)  {
0780          PEnv_t  e = PEnv_t(env);
0781          PCont_t c = PCont_t(e->fObject);
0782          e->fIterator.first = 0;
0783          e->fIterator.second = c->size() > 0 ? c->test(e->fIterator.first) : false ;  // Iterator actually hold the value.
0784          e->fSize  = c->size();
0785          return &(e->fIterator.second);
0786       }
0787       static void* next(void* env)  {
0788          PEnv_t  e = PEnv_t(env);
0789          PCont_t c = PCont_t(e->fObject);
0790          for (; e->fIdx > 0 && e->fIterator.first != c->size(); ++(e->fIterator.first), --e->fIdx){ }
0791          e->fIterator.second = (e->fIterator.first != c->size()) ? c->test(e->fIterator.first) : false;
0792          return &(e->fIterator.second);
0793       }
0794       static void* construct(void*,size_t)  {
0795          // Nothing to construct.
0796          return nullptr;
0797       }
0798       static void* collect(void *coll, void *array)  {
0799          PCont_t  c = PCont_t(coll);
0800          PValue_t m = PValue_t(array); // 'start' is a buffer outside the container.
0801          for (size_t i=0; i != c->size(); ++i, ++m )
0802             *m = c->test(i);
0803          return nullptr;
0804       }
0805       static void destruct(void*,size_t)  {
0806          // Nothing to destruct.
0807       }
0808 
0809       //static const bool fgLargeIterator = sizeof(typename Cont_t::iterator) > fgIteratorArenaSize;
0810       //typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
0811 
0812       struct Iterators {
0813          union PtrSize_t { size_t fIndex; void *fAddress; };
0814          typedef std::pair<PtrSize_t,Bool_t> iterator;
0815          // In the end iterator we store the bitset pointer
0816          // and do not use the 'second' part of the pair.
0817          // In the other iterator we store the index
0818          // and the value.
0819 
0820          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0821             iterator *begin = new (*begin_arena) iterator;
0822             begin->first.fIndex = 0;
0823             begin->second = false;
0824             iterator *end = new (*end_arena) iterator;
0825             end->first.fAddress = coll;
0826             end->second = false;
0827          }
0828          static void* copy(void *dest_arena, const void *source_ptr) {
0829             const iterator *source = (const iterator *)(source_ptr);
0830             new (dest_arena) iterator(*source);
0831             return dest_arena;
0832          }
0833          static void* next(void *iter_loc, const void *end_loc) {
0834             const iterator *end = (const iterator *)(end_loc);
0835             PCont_t c = (PCont_t)end->first.fAddress;
0836             iterator *iter = (iterator *)(iter_loc);
0837             if (iter->first.fIndex != c->size()) {
0838                iter->second = c->test(iter->first.fIndex);
0839                ++(iter->first.fIndex);
0840             }
0841             return &(iter->second);
0842          }
0843          static void destruct1(void *iter_ptr) {
0844             iterator *start = (iterator *)(iter_ptr);
0845             start->~iterator();
0846          }
0847          static void destruct2(void *begin_ptr, void *end_ptr) {
0848             iterator *start = (iterator *)(begin_ptr);
0849             iterator *end = (iterator *)(end_ptr);
0850             start->~iterator();
0851             end->~iterator();
0852          }
0853       };
0854       typedef Iterators Iterators_t;
0855    };
0856 
0857    template <typename Bitset_t>
0858    struct TCollectionProxyInfo::Pushback<Internal::TStdBitsetHelper<Bitset_t>  > : public TCollectionProxyInfo::Type<Internal::TStdBitsetHelper<Bitset_t> > {
0859       using InfoBase_t = TCollectionProxyInfo::Type<Internal::TStdBitsetHelper<Bitset_t> >;
0860       using typename InfoBase_t::Cont_t;
0861       using typename InfoBase_t::Iter_t;
0862       using typename InfoBase_t::Value_t;
0863       using typename InfoBase_t::Env_t;
0864       using typename InfoBase_t::PEnv_t;
0865       using typename InfoBase_t::PCont_t;
0866       using typename InfoBase_t::PValue_t;
0867 
0868       static void resize(void*,size_t)  {
0869       }
0870       static void* feed(void *from, void *to, size_t size)  {
0871          PCont_t  c = PCont_t(to);
0872          PValue_t m = PValue_t(from);
0873          for (size_t i=0; i<size; ++i, ++m)
0874             c->set(i,*m);
0875          return nullptr;
0876       }
0877       static int value_offset()  {
0878          return 0;
0879       }
0880    };
0881 
0882 } // namespace Detail
0883 
0884 // For (reasonable) backward compatibility:
0885 using namespace Detail;
0886 } // namespace ROOT
0887 
0888 #endif