// @(#)root/cont:$Name: $:$Id: TCollectionProxy.h,v 1.9 2005/06/01 15:43:18 pcanal Exp $ // Author: Markus Frank 28/10/04 /************************************************************************* * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #ifndef ROOT_TCollectionProxy #define ROOT_TCollectionProxy ////////////////////////////////////////////////////////////////////////// // // // Small helper to save proxy environment in the event of // recursive calls. // ////////////////////////////////////////////////////////////////////////// #include // Forward declarations class TBuffer; class TClassStreamer; class TMemberStreamer; class TGenCollectionProxy; class TGenCollectionStreamer; class TVirtualCollectionProxy; class TEmulatedCollectionProxy; #if defined(_WIN32) #if _MSC_VER<1300 #define TYPENAME #define R__VCXX6 #else #define TYPENAME typename #endif #else #define TYPENAME typename #endif namespace ROOT { /** @class TCollectionProxy::Environ TCollectionProxy.h TCollectionProxy.h * * Small helper to save proxy environment in the event of * recursive calls. * * @author M.Frank * @version 1.0 * @date 10/10/2004 */ #ifndef __CINT__ template struct Environ { typedef T Iter_t; char buff[64]; size_t idx; size_t size; void* object; void* start; void* temp; bool delete_temp; int refCount; size_t space; T& iter() { return *(T*)buff; } }; #else template struct Environ; #endif #if defined(R__VCXX6) template void Destruct(T* obj) { obj->~T(); } #endif } /** @class TCollectionProxy TCollectionProxy.h cont/TCollectionProxy.h * * TCollectionProxy * Interface to collection proxy and streamer generator. * * Proxy around an arbitrary container, which implements basic * functionality and iteration. The purpose of this implementation * is to shield any generated dictionary implementation from the * underlying streamer/proxy implementation and only expose * the creation fucntions. * * In particular this is used to implement splitting and abstract * element access of any container. Access to compiled code is necessary * to implement the abstract iteration sequence and functionality like * size(), clear(), resize(). resize() may be a void operation. * * @author M.Frank * @version 1.0 */ class TCollectionProxy { public: typedef TVirtualCollectionProxy Proxy_t; #ifdef R__HPUX typedef const type_info& Info_t; #else typedef const std::type_info& Info_t; #endif template struct pair_holder { T first; Q second; pair_holder() {} pair_holder(const pair_holder& c) : first(c.first), second(c.second) {} ~pair_holder() {} }; template struct Address { static void* address(T ref) { return (void*)&ref; } }; /** @class TCollectionProxy::fType TCollectionProxy.h TCollectionProxy.h * * Small helper to encapsulate basic data accesses for * all STL continers. * * @author M.Frank * @version 1.0 * @date 10/10/2004 */ template struct Type #ifdef R__KCC : public Address #else : public Address #endif { typedef T Cont_t; typedef typename T::iterator Iter_t; typedef typename T::value_type Value_t; typedef ROOT::Environ Env_t; typedef Env_t *PEnv_t; typedef Cont_t *PCont_t; typedef Value_t *PValue_t; static inline PCont_t object(void* ptr) { return PCont_t(PEnv_t(ptr)->object); } static void* size(void* env) { PEnv_t e = PEnv_t(env); e->size = PCont_t(e->object)->size(); return &e->size; } static void* clear(void* env) { object(env)->clear(); return 0; } static void* first(void* env) { PEnv_t e = PEnv_t(env); PCont_t c = PCont_t(e->object); // Assume iterators do not need destruction ::new(e->buff) Iter_t(c->begin()); e->size = c->size(); if ( 0 == e->size ) return e->start = 0; #ifdef R__KCC TYPENAME T::value_type& ref = *(e->iter()); #else TYPENAME T::const_reference ref = *(e->iter()); #endif return e->start = address(ref); } static void* next(void* env) { PEnv_t e = PEnv_t(env); PCont_t c = PCont_t(e->object); for (; e->idx > 0 && e->iter() != c->end(); ++(e->iter()), --e->idx ); // TODO: Need to find something for going backwards.... if ( e->iter() == c->end() ) return 0; #ifdef R__KCC TYPENAME T::value_type& ref = *(e->iter()); #else TYPENAME T::const_reference ref = *(e->iter()); #endif return address(ref); } static void* construct(void* env) { PEnv_t e = PEnv_t(env); PValue_t m = PValue_t(e->start); for (size_t i=0; isize; ++i, ++m) ::new(m) Value_t(); return 0; } static void* collect(void* env) { PEnv_t e = PEnv_t(env); PCont_t c = PCont_t(e->object); PValue_t m = PValue_t(e->start); for (Iter_t i=c->begin(); i != c->end(); ++i, ++m ) ::new(m) Value_t(*i); return 0; } static void* destruct(void* env) { PEnv_t e = PEnv_t(env); PValue_t m = PValue_t(e->start); #if defined(R__VCXX6) PCont_t c = PCont_t(e->object); for (size_t i=0; i < e->size; ++i, ++m ) ROOT::Destruct(m); #else for (size_t i=0; i < e->size; ++i, ++m ) m->~Value_t(); #endif return 0; } }; /** @class TCollectionProxy::Map TCollectionProxy.h TCollectionProxy.h * * Small helper to encapsulate all necessary data accesses for * containers like vector, list, deque * * @author M.Frank * @version 1.0 * @date 10/10/2004 */ template struct Pushback : public Type { typedef T Cont_t; typedef typename T::iterator Iter_t; typedef typename T::value_type Value_t; typedef ROOT::Environ Env_t; typedef Env_t *PEnv_t; typedef Cont_t *PCont_t; typedef Value_t *PValue_t; static void* resize(void* env) { PEnv_t e = PEnv_t(env); PCont_t c = PCont_t(e->object); c->resize(e->size); e->idx = 0; return e->start = address(*c->begin()); } static void* feed(void* env) { PEnv_t e = PEnv_t(env); PCont_t c = PCont_t(e->object); PValue_t m = PValue_t(e->start); for (size_t i=0; isize; ++i, ++m) c->push_back(*m); return 0; } static int value_offset() { return 0; } }; /** @class TCollectionProxy::Map TCollectionProxy.h TCollectionProxy.h * * Small helper to encapsulate all necessary data accesses for * containers like set, multiset etc. * * @author M.Frank * @version 1.0 * @date 10/10/2004 */ template struct Insert : public Type { typedef T Cont_t; typedef typename T::iterator Iter_t; typedef typename T::value_type Value_t; typedef ROOT::Environ Env_t; typedef Env_t *PEnv_t; typedef Cont_t *PCont_t; typedef Value_t *PValue_t; static void* feed(void* env) { PEnv_t e = PEnv_t(env); PCont_t c = PCont_t(e->object); PValue_t m = PValue_t(e->start); for (size_t i=0; isize; ++i, ++m) c->insert(*m); return 0; } static void* resize(void* /* env */ ) { return 0; } static int value_offset() { return 0; } }; /** @class TCollectionProxy::Map TCollectionProxy.h TCollectionProxy.h * * Small helper to encapsulate all necessary data accesses for * containers like set, multiset etc. * * @author M.Frank * @version 1.0 * @date 10/10/2004 */ template struct MapInsert : public Type { typedef T Cont_t; typedef typename T::iterator Iter_t; typedef typename T::value_type Value_t; typedef ROOT::Environ Env_t; typedef Env_t *PEnv_t; typedef Cont_t *PCont_t; typedef Value_t *PValue_t; static void* feed(void* env) { PEnv_t e = PEnv_t(env); PCont_t c = PCont_t(e->object); PValue_t m = PValue_t(e->start); for (size_t i=0; isize; ++i, ++m) c->insert(*m); return 0; } static void* resize(void* /* env */ ) { return 0; } static int value_offset() { return ((char*)&((PValue_t(0x1000))->second)) - ((char*)PValue_t(0x1000)); } }; /// Generate emulated collection proxy for a given class static TVirtualCollectionProxy* genEmulatedProxy(const char* class_name); /// Generate emulated class streamer for a given collection class static TClassStreamer* genEmulatedClassStreamer(const char* class_name); /// Generate emulated member streamer for a given collection class static TMemberStreamer* genEmulatedMemberStreamer(const char* class_name); /// Generate proxy from static functions static Proxy_t* genExplicitProxy( Info_t info, size_t iter_size, size_t value_diff, int value_offset, void* (*size_func)(void*), void* (*resize_func)(void*), void* (*clear_func)(void*), void* (*first_func)(void*), void* (*next_func)(void*), void* (*construct_func)(void*), void* (*destruct_func)(void*), void* (*feed_func)(void*), void* (*collect_func)(void*) ); /// Generate proxy from template template static Proxy_t* genProxy(const T&) { pair_holder* p = (pair_holder*)0x1000; return genExplicitProxy(typeid(TYPENAME T::Cont_t), sizeof(TYPENAME T::Iter_t), (((char*)&p->second)-((char*)&p->first)), T::value_offset(), T::size, T::resize, T::clear, T::first, T::next, T::construct, T::destruct, T::feed, T::collect); } /// Generate streamer from static functions static TGenCollectionStreamer* genExplicitStreamer( Info_t info, size_t iter_size, size_t value_diff, int value_offset, void* (*size_func)(void*), void* (*resize_func)(void*), void* (*clear_func)(void*), void* (*first_func)(void*), void* (*next_func)(void*), void* (*construct_func)(void*), void* (*destruct_func)(void*), void* (*feed_func)(void*), void* (*collect_func)(void*) ); /// Generate class streamer from static functions static TClassStreamer* genExplicitClassStreamer( Info_t info, size_t iter_size, size_t value_diff, int value_offset, void* (*size_func)(void*), void* (*resize_func)(void*), void* (*clear_func)(void*), void* (*first_func)(void*), void* (*next_func)(void*), void* (*construct_func)(void*), void* (*destruct_func)(void*), void* (*feed_func)(void*), void* (*collect_func)(void*) ); /// Generate class streamer from template template static TClassStreamer* genClassStreamer(const T&) { pair_holder* p = (pair_holder*)0x1000; return genExplicitClassStreamer(typeid(TYPENAME T::Cont_t), sizeof(TYPENAME T::Iter_t), (((char*)&p->second)-((char*)&p->first)), T::value_offset(), T::size, T::resize, T::clear, T::first, T::next, T::construct, T::destruct, T::feed, T::collect); } /// Generate member streamer from static functions static TMemberStreamer* genExplicitMemberStreamer(Info_t info, size_t iter_size, size_t value_diff, int value_offset, void* (*size_func)(void*), void* (*resize_func)(void*), void* (*clear_func)(void*), void* (*first_func)(void*), void* (*next_func)(void*), void* (*construct_func)(void*), void* (*destruct_func)(void*), void* (*feed_func)(void*), void* (*collect_func)(void*) ); /// Generate member streamer from template template static TMemberStreamer* genMemberStreamer(const T&) { pair_holder* p = (pair_holder*)0x1000; return genExplicitMemberStreamer( typeid(TYPENAME T::Cont_t), sizeof(TYPENAME T::Iter_t), (((char*)&p->second)-((char*)&p->first)), T::value_offset(), T::size, T::resize, T::clear, T::first, T::next, T::construct, T::destruct, T::feed, T::collect); } }; /** @class TCollectionStreamer TCollectionProxy.h cont/TCollectionProxy.h * * TEmulatedClassStreamer * * Class streamer object to implement TClassStreamr functionality * for I/O emulation. * * @author M.Frank * @version 1.0 */ class TCollectionStreamer { protected: TGenCollectionProxy* fStreamer; /// Pointer to worker streamer /// Issue Error about invalid proxy void InvalidProxyError(); public: /// Initializing constructor TCollectionStreamer(); /// Copy constructor TCollectionStreamer(const TCollectionStreamer& c); /// Standard destructor virtual ~TCollectionStreamer(); /// Attach worker proxy void AdoptStreamer(TGenCollectionProxy* streamer); /// Streamer for I/O handling void Streamer(TBuffer &refBuffer, void *pObject, int siz); }; #include "TClassStreamer.h" /** @class TEmulatedClassStreamer TCollectionProxy.h cont/TCollectionProxy.h * * TEmulatedClassStreamer * * Class streamer object to implement TClassStreamr functionality * for I/O emulation. * * @author M.Frank * @version 1.0 */ class TCollectionClassStreamer : public TClassStreamer, public TCollectionStreamer { public: /// Initializing constructor TCollectionClassStreamer() : TClassStreamer(0) { } /// Copy constructor TCollectionClassStreamer(const TCollectionClassStreamer& c) : TClassStreamer(c), TCollectionStreamer(c) { } /// Standard destructor virtual ~TCollectionClassStreamer() { } /// Streamer for I/O handling virtual void operator()(TBuffer &buff, void *pObj) { Streamer(buff,pObj,0); } }; #include "TMemberStreamer.h" /** @class TCollectionMemberStreamer TCollectionProxy.h cont/TCollectionProxy.h * * TCollectionMemberStreamer * * Class streamer object to implement TMemberStreamer functionality * for I/O emulation. * * @author M.Frank * @version 1.0 */ class TCollectionMemberStreamer : public TMemberStreamer, public TCollectionStreamer { public: /// Initializing constructor TCollectionMemberStreamer() : TMemberStreamer(0) { } /// Copy constructor TCollectionMemberStreamer(const TCollectionMemberStreamer& c) : TMemberStreamer(c), TCollectionStreamer(c) { } /// Standard destructor virtual ~TCollectionMemberStreamer() { } /// Streamer for I/O handling virtual void operator()(TBuffer &buff,void *pObj,Int_t siz=0) { Streamer(buff, pObj, siz); } }; #ifndef __CINT__ // Need specialization for boolean references due to stupid STL vector template<> inline void* TCollectionProxy::Address::const_reference>::address(std::vector::const_reference ) { return 0; } #endif #endif