CollectionProxy.h

Go to the documentation of this file.
00001 // @(#)root/reflex:$Id: CollectionProxy.h 36698 2010-11-16 16:40:22Z axel $
00002 // Author: Markus Frank 2004
00003 
00004 // Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
00005 //
00006 // Permission to use, copy, modify, and distribute this software for any
00007 // purpose is hereby granted without fee, provided that this copyright and
00008 // permissions notice appear in all copies and derivatives.
00009 //
00010 // This software is provided "as is" without express or implied warranty.
00011 
00012 #ifndef Reflex_CollectionProxy
00013 #define Reflex_CollectionProxy 1 1
00014 
00015 #include <cstddef>
00016 
00017 // Macro indicating the version of the Collection Proxy interface followed
00018 // by this Reflex build, this must match the version number of
00019 // ROOT_COLLECTIONPROXY_VERSION in ROOT's TVirtutalCollectionProxy.h
00020 
00021 #define REFLEX_COLLECTIONPROXY_VERSION 3
00022 
00023 // Forward declarations
00024 namespace std {
00025 template <class T, class A> class deque;
00026 template <class T, class A> class vector;
00027 template <class T, class A> class list;
00028 template <class T, class A> class queue;
00029 template <class T, class A> class stack;
00030 template <class K, class T, class A> class set;
00031 template <class K, class T, class A> class multiset;
00032 template <class K, class T, class R, class A> class map;
00033 template <class K, class T, class R, class A> class multimap;
00034 template <class T> class allocator;
00035 }
00036 // Hash map forward declarations
00037 #if defined(__GNUC__)
00038 namespace __gnu_cxx {  // GNU GCC
00039 template <class T, class F, class E, class A> class hash_set;
00040 template <class T, class F, class E, class A> class hash_multiset;
00041 template <class K, class T, class F, class E, class A> class hash_map;
00042 template <class K, class T, class F, class E, class A> class hash_multimap;
00043 }
00044 #elif  defined(_WIN32)
00045 namespace stdext {     // Visual C++
00046 template <class K, class T, class A> class hash_set;
00047 template <class K, class T, class A> class hash_multiset;
00048 template <class K, class T, class R, class A> class hash_map;
00049 template <class K, class T, class R, class A> class hash_multimap;
00050 }
00051 #endif
00052 
00053 namespace Reflex  {
00054 #ifndef __CINT__
00055 struct EnvironBase {
00056    EnvironBase(): fIdx(0),
00057       fSize(0),
00058       fObject(0),
00059       fStart(0),
00060       fTemp(0),
00061       fDeleteTemp(false),
00062       fRefSize(1),
00063       fSpace(0) {
00064       //   fprintf("Running default constructor on %p\n",this);
00065    }
00066 
00067 
00068    virtual ~EnvironBase() {}
00069 
00070    size_t fIdx;
00071    size_t fSize;
00072    void* fObject;
00073    void* fStart;
00074    void* fTemp;
00075    bool fDeleteTemp;
00076    int fRefSize;
00077    size_t fSpace;
00078 };
00079 template <typename T> struct Environ: public EnvironBase {
00080    typedef T Iter_t;
00081    Iter_t fIterator;
00082    T&
00083    iter() { return fIterator; }
00084 
00085    static void*
00086    Create() {
00087       return new Environ();
00088    }
00089 
00090 
00091 };
00092 #else
00093 struct EnvironBase;
00094 template <typename T> struct Environ;
00095 #endif
00096 
00097 template <typename T> struct Address {
00098    static void*
00099    address(T ref) {
00100       return (void*)& ref;
00101    }
00102 
00103 
00104 };
00105 
00106 template <class T> struct CollType
00107 #ifdef _KCC  // KAI compiler
00108    : public Address<typename T::value_type&>
00109 #else
00110    : public Address<typename T::const_reference>
00111 #endif
00112 {
00113 #ifdef _KCC  // KAI compiler
00114    typedef Address<typename T::value_type&> Address_t;
00115 #else
00116    typedef Address<typename T::const_reference> Address_t;
00117 #endif
00118    typedef T Cont_t;
00119    typedef typename T::iterator Iter_t;
00120    typedef typename T::value_type Value_t;
00121    typedef Reflex::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    static inline PCont_t
00127    object(void* ptr) {
00128       return PCont_t(PEnv_t(ptr)->fObject);
00129    }
00130 
00131 
00132    static void*
00133    size(void* env) {
00134       PEnv_t e = PEnv_t(env);
00135       e->fSize = PCont_t(e->fObject)->size();
00136       return &e->fSize;
00137    }
00138 
00139 
00140    static void*
00141    clear(void* env) {
00142       object(env)->clear();
00143       return 0;
00144    }
00145 
00146 
00147    static void*
00148    first(void* env) {
00149       PEnv_t e = PEnv_t(env);
00150       PCont_t c = PCont_t(e->fObject);
00151       // Assume iterators do not need destruction
00152       e->fIterator = c->begin();
00153       e->fSize = c->size();
00154 
00155       if (0 == e->fSize) { return e->fStart = 0; }
00156 #ifdef _KCC  // KAI compiler
00157       typename T::value_type& ref = *(e->iter());
00158 #else
00159       typename T::const_reference ref = *(e->iter());
00160 #endif
00161       return e->fStart = Address_t::address(ref);
00162    }
00163 
00164 
00165    static void*
00166    next(void* env) {
00167       PEnv_t e = PEnv_t(env);
00168       PCont_t c = PCont_t(e->fObject);
00169 
00170       for ( ; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx) {}
00171 
00172       // TODO: Need to find something for going backwards....
00173       if (e->iter() == c->end()) { return 0; }
00174 #ifdef _KCC  // KAI compiler
00175       typename T::value_type& ref = *(e->iter());
00176 #else
00177       typename T::const_reference ref = *(e->iter());
00178 #endif
00179       return Address_t::address(ref);
00180    }
00181 
00182 
00183    static void*
00184    construct(void* what, size_t size) {
00185       PValue_t m = PValue_t(what);
00186 
00187       for (size_t i = 0; i < size; ++i, ++m) {
00188          ::new (m) Value_t();
00189       }
00190       return 0;
00191    }
00192 
00193 
00194    static void*
00195    collect(void* env) {
00196       PEnv_t e = PEnv_t(env);
00197       PCont_t c = PCont_t(e->fObject);
00198       PValue_t m = PValue_t(e->fStart);
00199 
00200       for (Iter_t i = c->begin(); i != c->end(); ++i, ++m) {
00201          ::new (m) Value_t(*i);
00202       }
00203       return 0;
00204    }
00205 
00206 
00207    static void
00208    destruct(void* what, size_t size) {
00209       PValue_t m = PValue_t(what);
00210 
00211       for (size_t i = 0; i < size; ++i, ++m) {
00212          m->~Value_t();
00213       }
00214    }
00215 
00216 
00217 };
00218 
00219 /** @class TCollectionProxy::Map TCollectionProxy.h TCollectionProxy.h
00220  *
00221  * Small helper to encapsulate all necessary data accesses for
00222  * containers like vector, list, deque
00223  *
00224  * @author  M.Frank
00225  * @version 1.0
00226  * @date    10/10/2004
00227  */
00228 template <class T> struct Pushback: public CollType<T> {
00229    typedef T Cont_t;
00230    typedef typename T::iterator Iter_t;
00231    typedef typename T::value_type Value_t;
00232    typedef Environ<Iter_t> Env_t;
00233    typedef Env_t* PEnv_t;
00234    typedef Cont_t* PCont_t;
00235    typedef Value_t* PValue_t;
00236    static void resize(void* obj, size_t n) {
00237       PCont_t c = PCont_t(obj);
00238       c->resize(n);
00239    }
00240 
00241    static void*
00242       feed(void*from,void *to,size_t size) {
00243       PValue_t m = PValue_t(from);
00244       PCont_t c  = PCont_t(to);
00245 
00246       for (size_t i = 0; i < size; ++i, ++m) {
00247          c->push_back(*m);
00248       }
00249       return 0;
00250    }
00251 
00252 
00253    static int
00254    value_offset() {
00255       return 0;
00256    }
00257 
00258 
00259 };
00260 
00261 /** @class TCollectionProxy::Map TCollectionProxy.h TCollectionProxy.h
00262  *
00263  * Small helper to encapsulate all necessary data accesses for
00264  * containers like set, multiset etc.
00265  *
00266  * @author  M.Frank
00267  * @version 1.0
00268  * @date    10/10/2004
00269  */
00270 template <class T> struct Insert: public CollType<T> {
00271    typedef T Cont_t;
00272    typedef typename T::iterator Iter_t;
00273    typedef typename T::value_type Value_t;
00274    typedef Environ<Iter_t> Env_t;
00275    typedef Env_t* PEnv_t;
00276    typedef Cont_t* PCont_t;
00277    typedef Value_t* PValue_t;
00278 
00279    static void*
00280       feed(void*from,void*to,size_t size) {
00281       PValue_t m = PValue_t(from);
00282       PCont_t c  = PCont_t(to);
00283 
00284       for (size_t i = 0; i < size; ++i, ++m) {
00285          c->insert(*m);
00286       }
00287       return 0;
00288    }
00289 
00290 
00291    static void resize(void* /* obj */, size_t) { }
00292 
00293 
00294    static int
00295    value_offset() {
00296       return 0;
00297    }
00298 
00299 
00300 };
00301 
00302 /** @class TCollectionProxy::Map TCollectionProxy.h TCollectionProxy.h
00303  *
00304  * Small helper to encapsulate all necessary data accesses for
00305  * containers like Set, multiset etc.
00306  *
00307  * @author  M.Frank
00308  * @version 1.0
00309  * @date    10/10/2004
00310  */
00311 template <class T> struct MapInsert: public CollType<T> {
00312    typedef T Cont_t;
00313    typedef typename T::iterator Iter_t;
00314    typedef typename T::value_type Value_t;
00315    typedef Environ<Iter_t> Env_t;
00316    typedef Env_t* PEnv_t;
00317    typedef Cont_t* PCont_t;
00318    typedef Value_t* PValue_t;
00319 
00320    static void*
00321       feed(void*from,void *to,size_t size) {
00322       PValue_t m = PValue_t(from);
00323       PCont_t  c = PCont_t(to);
00324 
00325       for (size_t i = 0; i < size; ++i, ++m) {
00326          c->insert(*m);
00327       }
00328       return 0;
00329    }
00330 
00331 
00332    static void resize(void* /* obj */, size_t) {
00333    }
00334 
00335 
00336    static int
00337    value_offset() {
00338       return ((char*) &((PValue_t(0x1000))->second)) - ((char*) PValue_t(0x1000));
00339    }
00340 
00341 
00342 };
00343 
00344 #ifndef __CINT__
00345 // Need specialization for boolean references due to stupid STL vector<bool>
00346 template <> inline void* Reflex::Address<std::vector<bool, std::allocator<bool> >::const_reference
00347 >::address(std::vector<bool, std::allocator<bool> >::const_reference) {
00348    return 0;
00349 }
00350 
00351 
00352 #endif
00353 
00354 }
00355 
00356 #include <vector>
00357 namespace Reflex  {
00358 /** @class CollFuncTable
00359  *
00360  * Table containing pointers to concrete functions to manipulate
00361  * Collections in a generic way
00362  *
00363  * @author  M.Frank
00364  */
00365 struct RFLX_API CollFuncTable  {
00366    size_t iter_size;
00367    size_t value_diff;
00368    int value_offset;
00369    void*  (*size_func)(void*);
00370    void   (*resize_func)(void*,size_t);
00371    void*  (*clear_func)(void*);
00372    void*  (*first_func)(void*);
00373    void*  (*next_func)(void*);
00374    void*  (*construct_func)(void*,size_t);
00375    void   (*destruct_func)(void*,size_t);
00376    void*  (*feed_func)(void*,void*,size_t);
00377    void*  (*collect_func)(void*);
00378    void*  (*create_env)();
00379 };
00380 
00381 template <typename T> struct CFTGenerator {
00382    static CollFuncTable*
00383    Generate() {
00384       typedef typename T::Value_t Value_t;
00385       typedef std::pair<Value_t, Value_t> Pair_t;
00386       Pair_t* ptr = (Pair_t*) 0x1000;
00387       CollFuncTable* p = new CollFuncTable();
00388       p->iter_size = sizeof(typename T::Iter_t);
00389       p->value_diff = ((char*) &ptr->second) - ((char*) &ptr->first);
00390       p->value_offset = T::value_offset();
00391       p->size_func = T::size;
00392       p->first_func = T::first;
00393       p->next_func = T::next;
00394       p->clear_func = T::clear;
00395       p->resize_func = T::resize;
00396       p->collect_func = T::collect;
00397       p->construct_func = T::construct;
00398       p->destruct_func = T::destruct;
00399       p->feed_func = T::feed;
00400       p->create_env = T::Env_t::Create;
00401       return p;
00402    } // Generate
00403 
00404 
00405 };
00406 struct CFTNullGenerator {
00407    static void*
00408    Void_func(void*) {
00409       return 0;
00410    }
00411 
00412 
00413    static void*
00414    Void_func0() { return 0; }
00415 
00416    static void
00417    Void_func2b(void*,size_t) { ; }
00418 
00419    static void*
00420    Void_func2(void*,size_t) { return 0; }
00421 
00422    static void*
00423    Void_func3(void*,void*,size_t) { return 0; }
00424 
00425    static CollFuncTable*
00426    Generate() {
00427       CollFuncTable* p = new CollFuncTable();
00428       p->iter_size = 4;
00429       p->value_diff = 0;
00430       p->value_offset = 0;
00431       p->size_func = Void_func;
00432       p->first_func = Void_func;
00433       p->next_func = Void_func;
00434       p->clear_func = Void_func;
00435       p->resize_func = Void_func2b;
00436       p->collect_func = Void_func;
00437       p->construct_func = Void_func2;
00438       p->destruct_func = Void_func2b;
00439       p->feed_func = Void_func3;
00440       p->create_env = Void_func0;
00441       return p;
00442    } // Generate
00443 
00444 
00445 };
00446 // General proxy (dummy)
00447 template <typename A> struct Proxy {};
00448 
00449 // Specialization for std::vector
00450 template <class T, class A> struct Proxy<std::vector<T, A> > {
00451    static CollFuncTable*
00452    Generate() {
00453       return CFTGenerator<Pushback<std::vector<T, A> > >::Generate();
00454    }
00455 
00456 
00457 };
00458 // Specialization for std::list
00459 template <class T, class A> struct Proxy<std::list<T, A> > {
00460    static CollFuncTable*
00461    Generate() {
00462       return CFTGenerator<Pushback<std::list<T, A> > >::Generate();
00463    }
00464 
00465 
00466 };
00467 // Specialization for std::deque
00468 template <class T, class A> struct Proxy<std::deque<T, A> > {
00469    static CollFuncTable*
00470    Generate() {
00471       return CFTGenerator<Pushback<std::deque<T, A> > >::Generate();
00472    }
00473 
00474 
00475 };
00476 // Specialization for std::set
00477 template <class K, class T, class A> struct Proxy<std::set<K, T, A> > {
00478    static CollFuncTable*
00479    Generate() {
00480       return CFTGenerator<Insert<std::set<K, T, A> > >::Generate();
00481    }
00482 
00483 
00484 };
00485 // Specialization for std::multiset
00486 template <class K, class T, class A> struct Proxy<std::multiset<K, T, A> > {
00487    static CollFuncTable*
00488    Generate() {
00489       return CFTGenerator<Insert<std::multiset<K, T, A> > >::Generate();
00490    }
00491 
00492 
00493 };
00494 // Specialization for std::map
00495 template <class K, class T, class R, class A> struct Proxy<std::map<K, T, R, A> > {
00496    static CollFuncTable*
00497    Generate() {
00498       return CFTGenerator<MapInsert<std::map<K, T, R, A> > >::Generate();
00499    }
00500 
00501 
00502 };
00503 // Specialization for std::multimap
00504 template <class K, class T, class R, class A> struct Proxy<std::multimap<K, T, R, A> > {
00505    static CollFuncTable*
00506    Generate() {
00507       return CFTGenerator<MapInsert<std::multimap<K, T, R, A> > >::Generate();
00508    }
00509 
00510 
00511 };
00512 // Specialization for std::queue -- not implemented
00513 template <class K, class T> struct Proxy<std::queue<K, T> > {
00514    static CollFuncTable*
00515    Generate() { return CFTNullGenerator::Generate(); }
00516 
00517 };
00518 // Specialization for std::stack -- not implemented
00519 template <class K, class T> struct Proxy<std::stack<K, T> > {
00520    static CollFuncTable*
00521    Generate() { return CFTNullGenerator::Generate(); }
00522 
00523 };
00524 #if defined(__GNUC__)
00525 // Specialization for __gnu_cxx::hash_set
00526 template <class T, class F, class E, class A> struct Proxy<__gnu_cxx::hash_set<T, F, E, A> > {
00527    static CollFuncTable*
00528    Generate() {
00529       return CFTGenerator<Insert<__gnu_cxx::hash_set<T, F, E, A> > >::Generate();
00530    }
00531 
00532 
00533 };
00534 // Specialization for __gnu_cxx::hash_multiset
00535 template <class T, class F, class E, class A> struct Proxy<__gnu_cxx::hash_multiset<T, F, E, A> > {
00536    static CollFuncTable*
00537    Generate() {
00538       return CFTGenerator<Insert<__gnu_cxx::hash_multiset<T, F, E, A> > >::Generate();
00539    }
00540 
00541 
00542 };
00543 // Specialization for __gnu_cxx::hash_map
00544 template <class K, class T, class F, class E, class A> struct Proxy<__gnu_cxx::hash_map<K, T, F, E, A> > {
00545    static CollFuncTable*
00546    Generate() {
00547       return CFTGenerator<MapInsert<__gnu_cxx::hash_map<K, T, F, E, A> > >::Generate();
00548    }
00549 
00550 
00551 };
00552 // Specialization for __gnu_cxx::hash_multimap
00553 template <class K, class T, class F, class E, class A> struct Proxy<__gnu_cxx::hash_multimap<K, T, F, E, A> > {
00554    static CollFuncTable*
00555    Generate() {
00556       return CFTGenerator<MapInsert<__gnu_cxx::hash_multimap<K, T, F, E, A> > >::Generate();
00557    }
00558 
00559 
00560 };
00561 #elif defined(_WIN32)
00562 // Specialization for stdext::hash_multiset
00563 template <class K, class T, class A> struct Proxy<stdext::hash_multiset<K, T, A> > {
00564    static CollFuncTable*
00565    Generate() {
00566       return CFTGenerator<Insert<stdext::hash_multiset<K, T, A> > >::Generate();
00567    }
00568 
00569 
00570 };
00571 // Specialization for stdext::hash_set
00572 template <class K, class T, class A> struct Proxy<stdext::hash_set<K, T, A> > {
00573    static CollFuncTable*
00574    Generate() {
00575       return CFTGenerator<Insert<stdext::hash_set<K, T, A> > >::Generate();
00576    }
00577 
00578 
00579 };
00580 // Specialization for stdext::hash_map
00581 template <class K, class T, class R, class A> struct Proxy<stdext::hash_map<K, T, R, A> > {
00582    static CollFuncTable*
00583    Generate() {
00584       return CFTGenerator<MapInsert<stdext::hash_map<K, T, R, A> > >::Generate();
00585    }
00586 
00587 
00588 };
00589 // Specialization for stdext::hash_multimap
00590 template <class K, class T, class R, class A> struct Proxy<stdext::hash_multimap<K, T, R, A> > {
00591    static CollFuncTable*
00592    Generate() {
00593       return CFTGenerator<MapInsert<stdext::hash_multimap<K, T, R, A> > >::Generate();
00594    }
00595 
00596 
00597 };
00598 #endif
00599 
00600 // Specialization for std::bitset
00601 template <typename B> struct StdBitSetHelper {};
00602 
00603 
00604 #ifndef __CINT__
00605 template <typename Bitset_t> struct CollType<StdBitSetHelper<Bitset_t> > : public Address<const bool&> {
00606    typedef Bitset_t Cont_t;
00607    typedef std::pair<size_t, bool> Iter_t;
00608    typedef bool Value_t;
00609    typedef Environ<Iter_t> Env_t;
00610    typedef Env_t* PEnv_t;
00611    typedef Cont_t* PCont_t;
00612    typedef Value_t* PValue_t;
00613 
00614    virtual ~CollType() {}
00615 
00616    static inline PCont_t
00617    object(void* ptr) {
00618       return PCont_t(PEnv_t(ptr)->fObject);
00619    }
00620 
00621 
00622    static void*
00623    size(void* env) {
00624       PEnv_t e = PEnv_t(env);
00625       e->fSize = PCont_t(e->fObject)->size();
00626       return &e->fSize;
00627    }
00628 
00629 
00630    static void*
00631    clear(void* env) {
00632       object(env)->reset();
00633       return 0;
00634    }
00635 
00636 
00637    static void*
00638    first(void* env) {
00639       PEnv_t e = PEnv_t(env);
00640       PCont_t c = PCont_t(e->fObject);
00641       e->fIterator.first = 0;
00642       e->fIterator.second = c->size() > 0 ? c->test(e->fIterator.first) : false;      // Iterator actually hold the value.
00643       e->fSize = c->size();
00644       return 0;
00645    }
00646 
00647 
00648    static void*
00649    next(void* env) {
00650       PEnv_t e = PEnv_t(env);
00651       PCont_t c = PCont_t(e->fObject);
00652 
00653       for ( ; e->fIdx > 0 && e->fIterator.first != c->size(); ++(e->fIterator.first), --e->fIdx) {}
00654       e->fIterator.second = (e->fIterator.first != c->size()) ? c->test(e->fIterator.first) : false;
00655       return 0;
00656    }
00657 
00658 
00659    static void*
00660    construct(void*,size_t) {
00661       // Nothing to construct.
00662       return 0;
00663    }
00664 
00665 
00666    static void*
00667    collect(void* env) {
00668       PEnv_t e = PEnv_t(env);
00669       PCont_t c = PCont_t(e->fObject);
00670       PValue_t m = PValue_t(e->fStart);    // 'start' is a buffer outside the container.
00671 
00672       for (size_t i = 0; i != c->size(); ++i, ++m) {
00673          *m = c->test(i);
00674       }
00675       return 0;
00676    }
00677 
00678 
00679    static void
00680    destruct(void*,size_t) {
00681       // Nothing to destruct.
00682    }
00683 
00684 
00685 };
00686 
00687 template <typename Bitset_t>
00688 struct Pushback<StdBitSetHelper<Bitset_t> > : public CollType<StdBitSetHelper<Bitset_t> > {
00689    typedef Bitset_t Cont_t;
00690    typedef bool Iter_t;
00691    typedef bool Value_t;
00692    typedef Environ<Iter_t> Env_t;
00693    typedef Env_t* PEnv_t;
00694    typedef Cont_t* PCont_t;
00695    typedef Value_t* PValue_t;
00696 
00697    static void resize(void* /*obj*/, size_t) { }
00698 
00699 
00700    static void*
00701    feed(void* env) {
00702       PEnv_t e = PEnv_t(env);
00703       PCont_t c = PCont_t(e->fObject);
00704       PValue_t m = PValue_t(e->fStart);    // Here start is actually a 'buffer' outside the container.
00705 
00706       for (size_t i = 0; i < e->fSize; ++i, ++m) {
00707          c->set(i, *m);
00708       }
00709       return 0;
00710    }
00711 
00712    static void*
00713       feed(void* from, void* to, size_t size) {
00714       PValue_t m = PValue_t(from);
00715       PCont_t c  = PCont_t(to);
00716 
00717       for (size_t i = 0; i < size; ++i, ++m) {
00718          c->set(i, *m);
00719       }
00720       return 0;
00721    }
00722 
00723 
00724    static int
00725    value_offset() {
00726       return 0;
00727    }
00728 
00729 
00730 };
00731 #endif
00732 
00733 template <typename B> struct Proxy<StdBitSetHelper<B> > {
00734    static CollFuncTable*
00735    Generate() {
00736       return CFTGenerator<Pushback<StdBitSetHelper<B> > >::Generate();
00737    }
00738 
00739 
00740 };
00741 }
00742 
00743 #endif // Reflex_CollectionProxy

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