TCollectionProxyInfo.h

Go to the documentation of this file.
00001 // @(#)root/cont:$Id: TCollectionProxyInfo.h 36061 2010-10-04 16:05:51Z pcanal $
00002 // Author: Markus Frank  28/10/04. Philippe Canal 02/01/2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #ifndef ROOT_TCollectionProxyInfo
00013 #define ROOT_TCollectionProxyInfo
00014 
00015 //////////////////////////////////////////////////////////////////////////
00016 //                                                                      //
00017 //  Small helper to gather the information neede to generate a          //
00018 //  Collection Proxy                                                    //
00019 //
00020 //////////////////////////////////////////////////////////////////////////
00021 
00022 #ifndef ROOT_TError
00023 #include "TError.h"
00024 #endif 
00025 #include <vector>
00026 
00027 #if defined(_WIN32)
00028    #if _MSC_VER<1300
00029       #define TYPENAME
00030       #define R__VCXX6
00031    #else
00032       #define TYPENAME typename
00033    #endif
00034 #else
00035    #define TYPENAME typename
00036 #endif
00037 
00038 namespace ROOT {
00039 
00040    class TCollectionProxyInfo {
00041       // This class is a place holder for the information needed
00042       // to create the proper Collection Proxy.
00043       // This is similar to Reflex's CollFuncTable.
00044 
00045 
00046    public:
00047 
00048   /** @class TCollectionProxyInfo::Environ TCollectionProxyInfo.h TCollectionProxyInfo.h
00049     *
00050     * Small helper to save proxy environment in the event of
00051     * recursive calls.
00052     *
00053     * @author  M.Frank
00054     * @version 1.0
00055     * @date    10/10/2004
00056     */
00057 #ifndef __CINT__
00058    struct EnvironBase {
00059    private:
00060       EnvironBase(const EnvironBase&); // Intentionally not implement, copy is not supported
00061       EnvironBase &operator=(const EnvironBase&); // Intentionally not implement, copy is not supported
00062    public:
00063       EnvironBase() : fIdx(0), fSize(0), fObject(0), fStart(0), fTemp(0), fUseTemp(kFALSE), fRefCount(1), fSpace(0)
00064       {
00065       }
00066       virtual ~EnvironBase() {}
00067       size_t              fIdx;
00068       size_t              fSize;
00069       void*               fObject;
00070       void*               fStart;
00071       void*               fTemp;
00072       Bool_t              fUseTemp;
00073       int                 fRefCount;
00074       size_t              fSpace;      
00075    };
00076    template <typename T> struct Environ : public EnvironBase {
00077       typedef T           Iter_t;
00078       Iter_t              fIterator;
00079       T& iter() { return fIterator; }
00080       static void        *Create() {
00081          return new Environ();
00082       }
00083    };
00084 #else
00085    struct EnvironBase;
00086    template <typename T> struct Environ;
00087 #endif
00088 
00089    template <class T, class Q> struct PairHolder {
00090       T first;
00091       Q second;
00092       PairHolder() {}
00093       PairHolder(const PairHolder& c) : first(c.first), second(c.second) {}
00094       virtual ~PairHolder() {}
00095    private:
00096       PairHolder& operator=(const PairHolder&);  // not implemented
00097    };
00098 
00099    template <class T> struct Address {
00100       virtual ~Address() {}
00101       static void* address(T ref) {
00102          return (void*)&ref;
00103       }
00104    };
00105 
00106    /** @class TCollectionProxyInfo::Type TCollectionProxyInfo.h TCollectionProxyInfo.h
00107     *
00108     * Small helper to encapsulate basic data accesses for
00109     * all STL continers.
00110     *
00111     * @author  M.Frank
00112     * @version 1.0
00113     * @date    10/10/2004
00114     */
00115    template <class T> struct Type
00116       : public Address<TYPENAME T::const_reference>
00117    {
00118       typedef T                      Cont_t;
00119       typedef typename T::iterator   Iter_t;
00120       typedef typename T::value_type Value_t;
00121       typedef Environ<Iter_t>        Env_t;
00122       typedef Env_t                 *PEnv_t;
00123       typedef Cont_t                *PCont_t;
00124       typedef Value_t               *PValue_t;
00125 
00126       virtual ~Type() {}
00127 
00128       static inline PCont_t object(void* ptr)   {
00129          return PCont_t(PEnv_t(ptr)->fObject);
00130       }
00131       static void* size(void* env)  {
00132          PEnv_t  e = PEnv_t(env);
00133          e->fSize   = PCont_t(e->fObject)->size();
00134          return &e->fSize;
00135       }
00136       static void* clear(void* env)  {
00137          object(env)->clear();
00138          return 0;
00139       }
00140       static void* first(void* env)  {
00141          PEnv_t  e = PEnv_t(env);
00142          PCont_t c = PCont_t(e->fObject);
00143 #if 0
00144          // Assume iterators do not need destruction
00145          ::new(e->buff) Iter_t(c->begin());
00146 #endif
00147          e->fIterator = c->begin();
00148          e->fSize  = c->size();
00149          if ( 0 == e->fSize ) return e->fStart = 0;
00150          TYPENAME T::const_reference ref = *(e->iter());
00151          return e->fStart = Type<T>::address(ref);
00152       }
00153       static void* next(void* env)  {
00154          PEnv_t  e = PEnv_t(env);
00155          PCont_t c = PCont_t(e->fObject);
00156          for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
00157          // TODO: Need to find something for going backwards....
00158          if ( e->iter() == c->end() ) return 0;
00159          TYPENAME T::const_reference ref = *(e->iter());
00160          return Type<T>::address(ref);
00161       }
00162       static void* construct(void *what, size_t size)  {
00163          PValue_t m = PValue_t(what);
00164          for (size_t i=0; i<size; ++i, ++m)
00165             ::new(m) Value_t();
00166          return 0;
00167       }
00168       static void* collect(void* env)  {
00169          PEnv_t   e = PEnv_t(env);
00170          PCont_t  c = PCont_t(e->fObject);
00171          PValue_t m = PValue_t(e->fStart);
00172          for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
00173             ::new(m) Value_t(*i);
00174          return 0;
00175       }
00176       static void destruct(void *what, size_t size)  {
00177          PValue_t m = PValue_t(what);
00178          for (size_t i=0; i < size; ++i, ++m )
00179             m->~Value_t();
00180       }
00181    };
00182 
00183    /** @class TCollectionProxyInfo::Map TCollectionProxyInfo.h TCollectionProxyInfo.h
00184     *
00185     * Small helper to encapsulate all necessary data accesses for
00186     * containers like vector, list, deque
00187     *
00188     * @author  M.Frank
00189     * @version 1.0
00190     * @date    10/10/2004
00191     */
00192    template <class T> struct Pushback : public Type<T> {
00193       typedef T                      Cont_t;
00194       typedef typename T::iterator   Iter_t;
00195       typedef typename T::value_type Value_t;
00196       typedef Environ<Iter_t>        Env_t;
00197       typedef Env_t                 *PEnv_t;
00198       typedef Cont_t                *PCont_t;
00199       typedef Value_t               *PValue_t;
00200       static void resize(void* obj, size_t n) {
00201          PCont_t c = PCont_t(obj);
00202          c->resize(n);
00203       }
00204       static void* feed(void *from, void *to, size_t size)  {
00205          PCont_t  c = PCont_t(to);
00206          PValue_t m = PValue_t(from);
00207          for (size_t i=0; i<size; ++i, ++m)
00208             c->push_back(*m);
00209          return 0;
00210       }
00211       static int value_offset()  {
00212          return 0;
00213       }
00214    };
00215 
00216    /** @class TCollectionProxyInfo::Map TCollectionProxyInfo.h TCollectionProxyInfo.h
00217     *
00218     * Small helper to encapsulate all necessary data accesses for
00219     * containers like set, multiset etc.
00220     *
00221     * @author  M.Frank
00222     * @version 1.0
00223     * @date    10/10/2004
00224     */
00225    template <class T> struct Insert : public Type<T> {
00226       typedef T                      Cont_t;
00227       typedef typename T::iterator   Iter_t;
00228       typedef typename T::value_type Value_t;
00229       typedef Environ<Iter_t>        Env_t;
00230       typedef Env_t                 *PEnv_t;
00231       typedef Cont_t                *PCont_t;
00232       typedef Value_t               *PValue_t;
00233       static void* feed(void *from, void *to, size_t size)  {
00234          PCont_t  c = PCont_t(to);
00235          PValue_t m = PValue_t(from);
00236          for (size_t i=0; i<size; ++i, ++m)
00237             c->insert(*m);
00238          return 0;
00239       }
00240       static void resize(void* /* obj */, size_t )  {
00241          ;
00242       }
00243       static int value_offset()  {
00244          return 0;
00245       }
00246    };
00247 
00248    /** @class TCollectionProxyInfo::Map TCollectionProxyInfo.h TCollectionProxyInfo.h
00249     *
00250     * Small helper to encapsulate all necessary data accesses for
00251     * containers like set, multiset etc.
00252     *
00253     * @author  M.Frank
00254     * @version 1.0
00255     * @date    10/10/2004
00256     */
00257    template <class T> struct MapInsert : public Type<T> {
00258       typedef T                      Cont_t;
00259       typedef typename T::iterator   Iter_t;
00260       typedef typename T::value_type Value_t;
00261       typedef Environ<Iter_t>        Env_t;
00262       typedef Env_t                 *PEnv_t;
00263       typedef Cont_t                *PCont_t;
00264       typedef Value_t               *PValue_t;
00265       static void* feed(void *from, void *to, size_t size)  {
00266          PCont_t  c = PCont_t(to);
00267          PValue_t m = PValue_t(from);
00268          for (size_t i=0; i<size; ++i, ++m)
00269             c->insert(*m);
00270          return 0;
00271       }
00272       static void resize(void* /* obj */, size_t )  {
00273          ;
00274       }
00275       static int value_offset()  {
00276          return ((char*)&((PValue_t(0x1000))->second)) - ((char*)PValue_t(0x1000));
00277       }
00278    };
00279 
00280       
00281    public:
00282 #ifndef __CINT__
00283       const type_info &fInfo;
00284 #endif
00285       size_t fIterSize;
00286       size_t fValueDiff;
00287       int    fValueOffset;
00288       void*  (*fSizeFunc)(void*);
00289       void   (*fResizeFunc)(void*,size_t);
00290       void*  (*fClearFunc)(void*);
00291       void*  (*fFirstFunc)(void*);
00292       void*  (*fNextFunc)(void*);
00293       void*  (*fConstructFunc)(void*,size_t);
00294       void   (*fDestructFunc)(void*,size_t);
00295       void*  (*fFeedFunc)(void*,void*,size_t);
00296       void*  (*fCollectFunc)(void*);
00297       void*  (*fCreateEnv)();
00298       
00299       // Set of function of direct iteration of the collections.
00300       void (*fGetIterators)(void *collection, void *&begin_arena, void *&end_arena); 
00301       // begin_arena and end_arena should contain the location of memory arena  of size fgIteratorSize. 
00302       // If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
00303       // Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
00304       
00305       void (*fCopyIterator)(void *&dest, const void *source);
00306       // Copy the iterator source, into dest.   dest should contain should contain the location of memory arena  of size fgIteratorSize.
00307       // If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
00308       // Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
00309       
00310       void* (*fNext)(void *iter, void *end);
00311       // iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
00312       // 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
00313       // If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
00314       // which case 'Next' will return the value of the pointer.
00315       
00316       void (*fDeleteSingleIterator)(void *iter);
00317       void (*fDeleteTwoIterators)(void *begin, void *end);
00318       // If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
00319       // Otherwise just call the iterator's destructor.
00320       
00321    public:
00322       TCollectionProxyInfo(const type_info& info,
00323                            size_t iter_size,
00324                            size_t value_diff,
00325                            int    value_offset,
00326                            void*  (*size_func)(void*),
00327                            void   (*resize_func)(void*,size_t),
00328                            void*  (*clear_func)(void*),
00329                            void*  (*first_func)(void*),
00330                            void*  (*next_func)(void*),
00331                            void*  (*construct_func)(void*,size_t),
00332                            void   (*destruct_func)(void*,size_t),
00333                            void*  (*feed_func)(void*,void*,size_t),
00334                            void*  (*collect_func)(void*),
00335                            void*  (*create_env)()
00336                            ) :
00337          fInfo(info), fIterSize(iter_size), fValueDiff(value_diff),
00338          fValueOffset(value_offset),
00339          fSizeFunc(size_func),fResizeFunc(resize_func),fClearFunc(clear_func),
00340          fFirstFunc(first_func),fNextFunc(next_func),fConstructFunc(construct_func),
00341          fDestructFunc(destruct_func),fFeedFunc(feed_func),fCollectFunc(collect_func),
00342          fCreateEnv(create_env),
00343          fGetIterators(0),fCopyIterator(0),fNext(0),fDeleteSingleIterator(0),fDeleteTwoIterators(0)
00344       {
00345       }
00346  
00347       /// Generate proxy from template
00348       template <class T> static ROOT::TCollectionProxyInfo* Generate(const T&)  {
00349          // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
00350          // template (used to described the behavior of the stl collection.
00351          // Typical use looks like:
00352          //      ::ROOT::TCollectionProxyInfo::Generate(TCollectionProxyInfo::Pushback< vector<string> >()));
00353          
00354          PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
00355             (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
00356          return new ROOT::TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
00357                                                sizeof(TYPENAME T::Iter_t),
00358                                                (((char*)&p->second)-((char*)&p->first)),
00359                                                T::value_offset(),
00360                                                T::size,
00361                                                T::resize,
00362                                                T::clear,
00363                                                T::first,
00364                                                T::next,
00365                                                T::construct,
00366                                                T::destruct,
00367                                                T::feed,
00368                                                T::collect,
00369                                                T::Env_t::Create);
00370       }
00371 
00372       template <class T> static ROOT::TCollectionProxyInfo Get(const T&)  {
00373 
00374          // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
00375          // template (used to described the behavior of the stl collection.
00376          // Typical use looks like:
00377          //      ::ROOT::TCollectionProxyInfo::Get(TCollectionProxyInfo::Pushback< vector<string> >()));
00378          
00379          PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
00380             (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
00381          return ROOT::TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
00382                                            sizeof(TYPENAME T::Iter_t),
00383                                            (((char*)&p->second)-((char*)&p->first)),
00384                                            T::value_offset(),
00385                                            T::size,
00386                                            T::resize,
00387                                            T::clear,
00388                                            T::first,
00389                                            T::next,
00390                                            T::construct,
00391                                            T::destruct,
00392                                            T::feed,
00393                                            T::collect,
00394                                            T::Env_t::Create);
00395       }
00396 
00397    };
00398 
00399    template <> struct TCollectionProxyInfo::Type<std::vector<bool> >
00400    : public TCollectionProxyInfo::Address<std::vector<bool>::const_reference>
00401    {
00402       typedef std::vector<bool>             Cont_t;
00403       typedef std::vector<bool>::iterator   Iter_t;
00404       typedef std::vector<bool>::value_type Value_t;
00405       typedef Environ<Iter_t>               Env_t;
00406       typedef Env_t                        *PEnv_t;
00407       typedef Cont_t                       *PCont_t;
00408       typedef Value_t                      *PValue_t;
00409       
00410       virtual ~Type() {}
00411       
00412       static inline PCont_t object(void* ptr)   {
00413          return PCont_t(PEnv_t(ptr)->fObject);
00414       }
00415       static void* size(void* env)  {
00416          PEnv_t  e = PEnv_t(env);
00417          e->fSize   = PCont_t(e->fObject)->size();
00418          return &e->fSize;
00419       }
00420       static void* clear(void* env)  {
00421          object(env)->clear();
00422          return 0;
00423       }
00424       static void* first(void* env)  {
00425          PEnv_t  e = PEnv_t(env);
00426          PCont_t c = PCont_t(e->fObject);
00427 #if 0
00428          // Assume iterators do not need destruction
00429          ::new(e->buff) Iter_t(c->begin());
00430 #endif
00431          e->fIterator = c->begin();
00432          e->fSize  = c->size();
00433          return 0;
00434       }
00435       static void* next(void* env)  {
00436          PEnv_t  e = PEnv_t(env);
00437          PCont_t c = PCont_t(e->fObject);
00438          for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
00439          // TODO: Need to find something for going backwards....
00440          return 0;
00441       }
00442       static void* construct(void*,size_t)  {
00443          // Nothing to construct.
00444          return 0;
00445       }
00446       static void* collect(void* env)  {
00447          PEnv_t   e = PEnv_t(env);
00448          PCont_t  c = PCont_t(e->fObject);
00449          PValue_t m = PValue_t(e->fStart); // 'start' is a buffer outside the container.
00450          for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
00451             ::new(m) Value_t(*i);
00452          return 0;
00453       }
00454       static void destruct(void*,size_t)  {
00455          // Nothing to destruct.
00456       }
00457    };
00458    
00459    template <> struct TCollectionProxyInfo::Pushback<std::vector<bool> > : public TCollectionProxyInfo::Type<std::vector<bool> > {
00460       typedef std::vector<bool>      Cont_t;
00461       typedef Cont_t::iterator       Iter_t;
00462       typedef Cont_t::value_type     Value_t;
00463       typedef Environ<Iter_t>        Env_t;
00464       typedef Env_t                 *PEnv_t;
00465       typedef Cont_t                *PCont_t;
00466       typedef Value_t               *PValue_t;
00467       
00468       static void resize(void* obj,size_t n) {
00469          PCont_t c = PCont_t(obj);
00470          c->resize(n);
00471       }
00472       static void* feed(void* from, void *to, size_t size)  {
00473          PCont_t  c = PCont_t(to);
00474          PValue_t m = PValue_t(from);
00475          for (size_t i=0; i<size; ++i, ++m)
00476             c->push_back(*m);
00477          return 0;
00478       }
00479       static int value_offset()  {
00480          return 0;
00481       }
00482    };
00483 
00484 #ifndef __CINT__
00485    // Need specialization for boolean references due to stupid STL vector<bool>
00486    template<> inline void* ::ROOT::TCollectionProxyInfo::Address<std::vector<bool>::const_reference>::address(std::vector<bool>::const_reference ) {
00487       R__ASSERT(0);
00488       return 0;
00489    }
00490 #endif
00491    
00492    template <typename T> class TStdBitsetHelper {
00493       // This class is intentionally empty, this is scaffolding to allow the equivalent
00494       // of 'template <int N> struct TCollectionProxyInfo::Type<std::bitset<N> >' which 
00495       // is not effective in C++ (as of gcc 4.3.3).
00496    };
00497 
00498 #ifndef __CINT__
00499    template <typename Bitset_t> struct TCollectionProxyInfo::Type<ROOT::TStdBitsetHelper<Bitset_t> > : public TCollectionProxyInfo::Address<const bool &>
00500    {
00501       typedef Bitset_t                Cont_t;
00502       typedef std::pair<size_t,bool>  Iter_t;
00503       typedef bool                    Value_t;
00504       typedef Environ<Iter_t>         Env_t;
00505       typedef Env_t                  *PEnv_t;
00506       typedef Cont_t                 *PCont_t;
00507       typedef Value_t                *PValue_t;
00508       
00509       virtual ~Type() {}
00510       
00511       static inline PCont_t object(void* ptr)   {
00512          return PCont_t(PEnv_t(ptr)->fObject);
00513       }
00514       static void* size(void* env)  {
00515          PEnv_t  e = PEnv_t(env);
00516          e->fSize   = PCont_t(e->fObject)->size();
00517          return &e->fSize;
00518       }
00519       static void* clear(void* env)  {
00520          object(env)->reset();
00521          return 0;
00522       }
00523       static void* first(void* env)  {
00524          PEnv_t  e = PEnv_t(env);
00525          PCont_t c = PCont_t(e->fObject);
00526          e->fIterator.first = 0;
00527          e->fIterator.second = c->size() > 0 ? c->test(e->fIterator.first) : false ;  // Iterator actually hold the value.
00528          e->fSize  = c->size();
00529          return 0;
00530       }
00531       static void* next(void* env)  {
00532          PEnv_t  e = PEnv_t(env);
00533          PCont_t c = PCont_t(e->fObject);
00534          for (; e->fIdx > 0 && e->fIterator.first != c->size(); ++(e->fIterator.first), --e->fIdx){ }
00535          e->fIterator.second = (e->fIterator.first != c->size()) ? c->test(e->fIterator.first) : false;
00536          return 0;
00537       }
00538       static void* construct(void*,size_t)  {
00539          // Nothing to construct.
00540          return 0;
00541       }
00542       static void* collect(void* env)  {
00543          PEnv_t   e = PEnv_t(env);
00544          PCont_t  c = PCont_t(e->fObject);
00545          PValue_t m = PValue_t(e->fStart); // 'start' is a buffer outside the container.
00546          for (size_t i=0; i != c->size(); ++i, ++m )
00547             *m = c->test(i);
00548          return 0;
00549       }
00550       static void destruct(void*,size_t)  {
00551          // Nothing to destruct.
00552       }
00553    };
00554    
00555    template <typename Bitset_t> 
00556    struct TCollectionProxyInfo::Pushback<ROOT::TStdBitsetHelper<Bitset_t>  > : public TCollectionProxyInfo::Type<TStdBitsetHelper<Bitset_t> > {
00557       typedef Bitset_t         Cont_t;
00558       typedef bool             Iter_t;
00559       typedef bool             Value_t;
00560       typedef Environ<Iter_t>  Env_t;
00561       typedef Env_t           *PEnv_t;
00562       typedef Cont_t          *PCont_t;
00563       typedef Value_t         *PValue_t;
00564       
00565       static void resize(void*,size_t)  {
00566       }
00567       static void* feed(void *from, void *to, size_t size)  {
00568          PCont_t  c = PCont_t(to);
00569          PValue_t m = PValue_t(from); 
00570          for (size_t i=0; i<size; ++i, ++m)
00571             c->set(i,*m);
00572          return 0;
00573       }
00574       static int value_offset()  {
00575          return 0;
00576       }
00577    };
00578 #endif
00579    
00580 }
00581 
00582 #endif

Generated on Tue Jul 5 14:11:27 2011 for ROOT_528-00b_version by  doxygen 1.5.1