From 0296a11b38bf48363a2dddcc4769959a320e79a5 Mon Sep 17 00:00:00 2001 From: Rene Brun <Rene.Brun@cern.ch> Date: Fri, 29 Oct 2004 18:03:11 +0000 Subject: [PATCH] from Markus Frank (main work) + Philippe & Rene Add support for all STL collections, including collections of collections. TTree has been extended to support split mode for most STL collections. The test program bench.cxx/TBench.cxx has been extended to test STL collections of objects or pointers. git-svn-id: http://root.cern.ch/svn/root/trunk@10431 27541ba8-7e3a-0410-8455-c3a389f83636 --- cont/inc/TCollectionProxy.h | 486 +++++++++++ cont/inc/TEmulatedCollectionProxy.h | 110 +++ cont/inc/TEmulatedMapProxy.h | 66 ++ cont/inc/TEmulatedVectorProxy.h | 10 +- cont/inc/TGenCollectionProxy.h | 311 +++++++ cont/inc/TGenCollectionStreamer.h | 89 ++ cont/inc/TVectorProxy.h | 5 +- cont/inc/TVirtualCollectionProxy.h | 11 +- cont/src/TCollectionProxy.cxx | 273 ++++++ cont/src/TEmulatedCollectionProxy.cxx | 437 ++++++++++ cont/src/TEmulatedMapProxy.cxx | 221 +++++ cont/src/TGenCollectionProxy.cxx | 714 ++++++++++++++++ cont/src/TGenCollectionStreamer.cxx | 490 +++++++++++ io/inc/TEmulatedCollectionProxy.h | 110 +++ io/inc/TEmulatedMapProxy.h | 66 ++ io/inc/TGenCollectionProxy.h | 311 +++++++ io/inc/TGenCollectionStreamer.h | 89 ++ io/src/TEmulatedCollectionProxy.cxx | 437 ++++++++++ io/src/TEmulatedMapProxy.cxx | 221 +++++ io/src/TGenCollectionProxy.cxx | 714 ++++++++++++++++ io/src/TGenCollectionStreamer.cxx | 490 +++++++++++ meta/src/TClass.cxx | 27 +- meta/src/TGenericClassInfo.cxx | 3 +- test/TBench.cxx | 1130 ++++++++++++++++++++++++- test/TBench.h | 304 ++++++- test/bench.cxx | 594 ++++++++++++- test/benchLinkDef.h | 22 +- tree/src/TBranchElement.cxx | 75 +- tree/src/TTree.cxx | 7 +- utils/src/RStl.cxx | 6 +- utils/src/rootcint.cxx | 74 +- 31 files changed, 7776 insertions(+), 127 deletions(-) create mode 100644 cont/inc/TCollectionProxy.h create mode 100644 cont/inc/TEmulatedCollectionProxy.h create mode 100644 cont/inc/TEmulatedMapProxy.h create mode 100644 cont/inc/TGenCollectionProxy.h create mode 100644 cont/inc/TGenCollectionStreamer.h create mode 100644 cont/src/TCollectionProxy.cxx create mode 100644 cont/src/TEmulatedCollectionProxy.cxx create mode 100644 cont/src/TEmulatedMapProxy.cxx create mode 100644 cont/src/TGenCollectionProxy.cxx create mode 100644 cont/src/TGenCollectionStreamer.cxx create mode 100644 io/inc/TEmulatedCollectionProxy.h create mode 100644 io/inc/TEmulatedMapProxy.h create mode 100644 io/inc/TGenCollectionProxy.h create mode 100644 io/inc/TGenCollectionStreamer.h create mode 100644 io/src/TEmulatedCollectionProxy.cxx create mode 100644 io/src/TEmulatedMapProxy.cxx create mode 100644 io/src/TGenCollectionProxy.cxx create mode 100644 io/src/TGenCollectionStreamer.cxx diff --git a/cont/inc/TCollectionProxy.h b/cont/inc/TCollectionProxy.h new file mode 100644 index 00000000000..e4a597af062 --- /dev/null +++ b/cont/inc/TCollectionProxy.h @@ -0,0 +1,486 @@ +// @(#)root/cont:$Name: $:$Id: TCollectionProxy.h,v 1.15 2004/10/13 15:30:22 rdm 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. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef __CINT__ +#include <typeinfo> + +// Forward declarations +class TBuffer; +class TClassStreamer; +class TMemberStreamer; +class TVirtualCollectionProxy; + +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 + */ + template <class T> 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; + T& iter() { return *(T*)buff; } + }; +} + +/** @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 <class T> 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 <class T> struct Type : public Address<typename T::const_reference> { + typedef T Cont_t; + typedef typename T::iterator Iter_t; + typedef typename T::value_type Value_t; + typedef ROOT::Environ<Iter_t> 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::reference 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::reference 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); + char* p = (char*)e->start; + for (size_t i=0; i<e->size; ++i, p+=sizeof(Value_t)) + new(p) 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); + for (size_t i=0; i < e->size; ++i, ++m ) + m->~Value_t(); + 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 <class T> struct Pushback : public Type<T> { + typedef T Cont_t; + typedef typename T::iterator Iter_t; + typedef typename T::value_type Value_t; + typedef ROOT::Environ<Iter_t> 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; i<e->size; ++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 <class T> struct Insert : public Type<T> { + typedef T Cont_t; + typedef typename T::iterator Iter_t; + typedef typename T::value_type Value_t; + typedef ROOT::Environ<Iter_t> 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; i<e->size; ++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 <class T> struct MapInsert : public Type<T> { + typedef T Cont_t; + typedef typename T::iterator Iter_t; + typedef typename T::value_type Value_t; + typedef ROOT::Environ<Iter_t> 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; i<e->size; ++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 Proxy_t* 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 <class T> static Proxy_t* genProxy() { + return genExplicitProxy(typeid(typename T::Cont_t), + sizeof(typename T::Iter_t), + sizeof(typename T::Value_t), + 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 Proxy_t* + 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 <class T> static TClassStreamer* genClassStreamer() { + return genExplicitClassStreamer(typeid(typename T::Cont_t), + sizeof(typename T::Iter_t), + sizeof(typename T::Value_t), + 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 <class T> static TMemberStreamer* genMemberStreamer() { + return genExplicitMemberStreamer( typeid(typename T::Cont_t), + sizeof(typename T::Iter_t), + sizeof(typename T::Value_t), + T::value_offset(), + T::size, + T::resize, + T::clear, + T::first, + T::next, + T::construct, + T::destruct, + T::feed, + T::collect); + } +}; + +/** @class TCollectionStreamer TEmulatedCollectionProxy.h cont/TEmulatedCollectionProxy.h + * + * TEmulatedClassStreamer + * + * Class streamer object to implement TClassStreamr functionality + * for I/O emulation. + * + * @author M.Frank + * @version 1.0 + */ +class TCollectionStreamer { +protected: + TVirtualCollectionProxy* fProxy; /// Pointer to worker proxy + + /// 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 AdoptProxy(TVirtualCollectionProxy* proxy); + /// Streamer for I/O handling + void Streamer(TBuffer &refBuffer, void *pObject, int siz); +}; + +#include "TClassStreamer.h" + +/** @class TEmulatedClassStreamer TEmulatedCollectionProxy.h cont/TEmulatedCollectionProxy.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 TEmulatedCollectionProxy.h cont/TEmulatedCollectionProxy.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); } +}; + +// Need specialization for boolean references due to stupid STL vector<bool> +template<> inline void* TCollectionProxy::Address<std::vector<bool>::const_reference>::address(std::vector<bool>::const_reference ) { + return 0; +} +#endif +#endif diff --git a/cont/inc/TEmulatedCollectionProxy.h b/cont/inc/TEmulatedCollectionProxy.h new file mode 100644 index 00000000000..6df63a42a23 --- /dev/null +++ b/cont/inc/TEmulatedCollectionProxy.h @@ -0,0 +1,110 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedCollectionProxy.h,v 1.15 2004/10/13 15:30:22 rdm 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_TEmulatedCollectionProxy +#define ROOT_TEmulatedCollectionProxy + +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedCollectionProxy +// +// Streamer around an arbitrary STL like container, which implements basic +// container functionality. +// +// Note: +// Although this class contains all the setup necessary to deal +// with maps, the map-like functionality is NOT supported. +// For optimization reasons this functionality is put into +// the class TEmulatedMapProxy. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionProxy.h" + +class TEmulatedCollectionProxy : public TGenCollectionProxy { + + /// Friend declaration + friend class TCollectionProxy; + +public: + /// Container type definition + typedef std::vector<char> Cont_t; + /// Pointer to container type + typedef Cont_t *PCont_t; +protected: + + /// Some hack to avoid const-ness + virtual TGenCollectionProxy* InitializeEx(); + + /// Object input streamer + void ReadItems(int nElements, TBuffer &b); + + /// Object output streamer + void WriteItems(int nElements, TBuffer &b); + + /// Shrink the container + void Shrink(UInt_t nCurr, UInt_t left, Bool_t force); + + /// Expand the container + void Expand(UInt_t nCurr, UInt_t left); + +public: + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy); + + /// Initializing constructor + TEmulatedCollectionProxy(const char* cl_name); + + /// Standard destructor + virtual ~TEmulatedCollectionProxy(); + + /// Virtual constructor + virtual void* New() const { return new Cont_t; } + + /// Virtual in-place constructor + virtual void* New(void* memory) const { return new(memory) Cont_t; } + + /// TVirtualCollectionProxy overload: Return the sizeof the collection object. + virtual UInt_t Sizeof() const { return sizeof(Cont_t); } + + /// Return the address of the value at index 'idx' + virtual void *At(UInt_t idx); + + /// Clear the container + virtual void Clear(const char *opt = ""); + + /// Resize the container + virtual void Resize(UInt_t n, Bool_t force_delete); + + /// Return the current size of the container + virtual UInt_t Size() const; + + /// Block allocation of containees + virtual void* Allocate(UInt_t n, Bool_t forceDelete); + + /// Block commit of containees + virtual void Commit(void* env); + + /// Streamer for I/O handling + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &buff, void *pObj, int siz) { + TGenCollectionProxy::Streamer(buff,pObj,siz); + } +}; + +#endif +#endif diff --git a/cont/inc/TEmulatedMapProxy.h b/cont/inc/TEmulatedMapProxy.h new file mode 100644 index 00000000000..43d266525c3 --- /dev/null +++ b/cont/inc/TEmulatedMapProxy.h @@ -0,0 +1,66 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedMapProxy.h,v 1.15 2004/10/13 15:30:22 rdm 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_TEmulatedMapProxy +#define ROOT_TEmulatedMapProxy +#define ROOT_TGenCollectionStreamer + +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedMapProxy +// +// Streamer around an arbitrary STL like container, which implements basic +// container functionality. +// +////////////////////////////////////////////////////////////////////////// + +#include "TEmulatedCollectionProxy.h" + +class TEmulatedMapProxy : public TEmulatedCollectionProxy { + +protected: + /// Map input streamer + void ReadMap(int nElements, TBuffer &b); + + /// Map output streamer + void WriteMap(int nElements, TBuffer &b); + +public: + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TEmulatedMapProxy(const TEmulatedMapProxy& copy); + + /// Initializing constructor + TEmulatedMapProxy(const char* cl_name); + + /// Standard destructor + virtual ~TEmulatedMapProxy(); + + /// Return the address of the value at index 'idx' + virtual void *At(UInt_t idx); + + /// Return the current size of the container + virtual UInt_t Size() const; + + /// Streamer for I/O handling + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &buff, void *pObj, int siz) { + TEmulatedCollectionProxy::Streamer(buff,pObj,siz); + } +}; + +#endif +#endif diff --git a/cont/inc/TEmulatedVectorProxy.h b/cont/inc/TEmulatedVectorProxy.h index dc9a0318ea8..e7e791b21c9 100644 --- a/cont/inc/TEmulatedVectorProxy.h +++ b/cont/inc/TEmulatedVectorProxy.h @@ -1,4 +1,4 @@ -// @(#)root/cont:$Name: $:$Id: TEmulatedVectorProxy.h,v 1.6 2004/10/07 17:08:53 brun Exp $ +// @(#)root/cont:$Name: $:$Id: TEmulatedVectorProxy.h,v 1.7 2004/10/08 15:19:37 brun Exp $ // Author: Philippe Canal 20/08/2003 /************************************************************************* @@ -9,8 +9,8 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -#ifndef Root_TEmulatedVectorProxy_h -#define Root_TEmulatedVectorProxy_h +#ifndef Root_TEmulatedVectorProxy +#define Root_TEmulatedVectorProxy ////////////////////////////////////////////////////////////////////////// // // @@ -72,9 +72,11 @@ public: void Clear(const char *opt = ""); // Clear the container void Resize(UInt_t n, Bool_t forceDelete); // Resize the container UInt_t Size() const; // Return the current size of the container + virtual void* Allocate(UInt_t n, Bool_t forceDelete) { Resize(n,forceDelete); return 0; } + virtual void Commit(void*) {} void Streamer(TBuffer &b); virtual void operator()(TBuffer &b, void *objp) { PushProxy(objp); Streamer(b); PopProxy(); } }; -#endif /* Root_TEmulatedVectorProxy_h */ +#endif diff --git a/cont/inc/TGenCollectionProxy.h b/cont/inc/TGenCollectionProxy.h new file mode 100644 index 00000000000..595b0ad5282 --- /dev/null +++ b/cont/inc/TGenCollectionProxy.h @@ -0,0 +1,311 @@ +// @(#)root/cont:$Name: $:$Id: TGenCollectionProxy.h,v 1.15 2004/10/13 15:30:22 rdm 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_TGenCollectionProxy +#define ROOT_TGenCollectionProxy +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionProxy +// +// Proxy around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TVirtualCollectionProxy.h" +#include "TCollectionProxy.h" +#include <typeinfo> +#include <string> + +class TGenCollectionProxy + : public TVirtualCollectionProxy, + public TCollectionProxy +{ + + /// Friend declaration + friend class TCollectionProxy; + +public: + + enum { + // Those 'bits' are used in conjunction with CINT's bit to store the 'type' + // info into one int + R__BIT_ISSTRING = 0x20000000, // We can optimized a value operation when the content are strings + R__BIT_ISTSTRING = 0x40000000, + kBOOL_t = 21 + }; + + + /** @class TGenCollectionProxy::Value TGenCollectionProxy.h TGenCollectionProxy.h + * + * Small helper to describe the Value_type or the key_type + * of an STL container. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ + struct Value { + ROOT::NewFunc_t fCtor; // Method cache for containee constructor + ROOT::DesFunc_t fDtor; // Method cache for containee destructor + ROOT::DelFunc_t fDelete; // Method cache for containee delete + unsigned int fCase; // type of data of Value_type + TClass* fType; // TClass of Value_type in collection + EDataType fKind; // kind of ROOT-fundamental type + size_t fSize; // fSize of the contained object + Value(const Value& inside); + Value(const std::string& info); + }; + + /**@class StreamHelper + * + * Helper class to facilitate I/O + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ + union StreamHelper { + bool boolean; + Char_t s_char; + Short_t s_short; + Int_t s_int; + Long_t s_long; + Long64_t s_longlong; + Float_t flt; + Double_t dbl; + UChar_t u_char; + UShort_t u_short; + UInt_t u_int; + ULong_t u_long; + ULong64_t u_longlong; + void* p_void; + void** pp_void; + char* kchar; + TString* tstr; + void* ptr() { + return *(&this->p_void); + } + std::string* str() { + return (std::string*)this; + } + const char* c_str() { + return ((std::string*)this)->c_str(); + } + const char* c_pstr() { + return (*(std::string**)this)->c_str(); + } + void set(void* p) { + *(&this->p_void) = p; + } + void read_std_string(TBuffer& b) { + TString s; + s.Streamer(b); + ((std::string*)this)->assign(s.Data()); + } + void* read_tstring(TBuffer& b) { + *((TString*)this) = ""; + ((TString*)this)->Streamer(b); + return this; + } + void read_std_string_pointer(TBuffer& b) { + TString s; + std::string* str = (std::string*) (ptr() ? ptr() : new std::string()); + s.Streamer(b); + *str = s; + set(str); + } + void write_std_string_pointer(TBuffer& b) { + const char* c = (const char*)(ptr() ? (*(std::string**)this)->c_str() : ""); + TString(c).Streamer(b); + } + void read_any_object(Value* v, TBuffer& b) { + void* p = ptr(); + if ( p ) { + if ( v->fDelete ) { // Compiled content: call Destructor + (*v->fDelete)(p); + } + else if ( v->fType ) { // Emulated content: call TClass::Delete + v->fType->Destructor(p); + } + else if ( v->fDtor ) { + (*v->fDtor)(p); + ::operator delete(p); + } + else { + ::operator delete(p); + } + } + set( b.ReadObjectAny(v->fType) ); + } + + void read_tstring_pointer(bool vsn3, TBuffer& b) { + TString* s = (TString*)ptr(); + if ( vsn3 ) { + if ( !s ) s = new TString(); + s->Replace(0, s->Length(), 0, 0); + s->Streamer(b); + set(s); + return; + } + if ( s ) delete s; + set( b.ReadObjectAny(TString::Class()) ); + } + void write_tstring_pointer(TBuffer& b) { + b.WriteObjectAny(ptr(), TString::Class()); + } + }; + + /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h + * + * Small helper to execute (compiler) generated function for the + * access to STL or other containers. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ + struct Method { + typedef void* (*Call_t)(void*); + Call_t call; + Method() : call(0) { } + Method(Call_t c) : call(c) { } + Method(const Method& m) : call(m.call) { } + void* invoke(void* obj) const { return (*call)(obj); } + }; + +protected: + typedef ROOT::Environ<char[64]> Env_t; + typedef std::vector<Env_t*> Proxies_t; + + std::string fName; // Name of the class being proxied. + bool fPointers; // Flag to indicate if containee has pointers (key or value) + Method fClear; // Method cache for container accessors: clear container + Method fSize; // Container accessors: size of container + Method fResize; // Container accessors: resize container + Method fFirst; // Container accessors: generic iteration: first + Method fNext; // Container accessors: generic iteration: next + Method fConstruct; // Container accessors: block construct + Method fDestruct; // Container accessors: block destruct + Method fFeed; // Container accessors: block feed + Method fCollect; // Method to collect objects from container + Value* fValue; // Descriptor of the container value type + Value* fVal; // Descriptor of the Value_type + Value* fKey; // Descriptor of the key_type + Env_t* fEnv; // Address of the currently proxied object + int fValOffset; // Offset from key to value (in maps) + int fValDiff; // Offset between two consecutive value_types (memory layout). + Proxies_t fProxyList; // Stack of recursive proxies + int fSTL_type; // STL container type + Info_t fTypeinfo; // Type information + + /// Late initialization of collection proxy + virtual TGenCollectionProxy* Initialize() const; + /// Some hack to avoid const-ness + virtual TGenCollectionProxy* InitializeEx(); + /// Call to delete/destruct individual contained item + virtual void DeleteItem(bool force, void* ptr) const; + /// Allow to check function pointers + void CheckFunctions() const; + +public: + + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TGenCollectionProxy(const TGenCollectionProxy& copy); + + /// Initializing constructor + TGenCollectionProxy(Info_t typ, size_t iter_size); + + /// Standard destructor + virtual ~TGenCollectionProxy(); + + /// Return a pointer to the TClass representing the container + virtual TClass *GetCollectionClass(); + + /// Return the sizeof the collection object. + virtual UInt_t Sizeof() const; + + /// Push new proxy environment + virtual void PushProxy(void *objstart); + + /// Pop old proxy environment + virtual void PopProxy(); + + /// Return true if the content is of type 'pointer to' + virtual Bool_t HasPointers() const; + + /// Return a pointer to the TClass representing the content. + virtual TClass *GetValueClass(); + + /// Set pointer to the TClass representing the content. + virtual void SetValueClass(TClass *newcl); + + /// If the content is a simple numerical value, return its type (see TDataType) + virtual EDataType GetType(); + + /// Return the address of the value at index 'idx' + virtual void *At(UInt_t idx); + + /// Clear the container + virtual void Clear(const char *opt = ""); + + /// Resize the container + virtual void Resize(UInt_t n, Bool_t force_delete); + + /// Return the current size of the container + virtual UInt_t Size() const; + + /// Block allocation of containees + virtual void* Allocate(UInt_t n, Bool_t forceDelete); + + /// Block commit of containees + virtual void Commit(void* env); + + /// Streamer function + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &refBuffer, void *pObject, int siz); + + /// TClassStreamer I/O overload + virtual void operator()(TBuffer &refBuffer, void *pObject); +}; + +template <typename T> +struct AnyCollectionProxy : public TGenCollectionProxy { + AnyCollectionProxy() + : TGenCollectionProxy(typeid(T::Cont_t),sizeof(T::Iter_t)) + { + fValDiff = sizeof(T::Value_t); + fValOffset = T::value_offset(); + fSize.call = T::size; + fResize.call = T::resize; + fNext.call = T::next; + fFirst.call = T::first; + fClear.call = T::clear; + fConstruct.call = T::construct; + fDestruct.call = T::destruct; + fFeed.call = T::feed; + CheckFunctions(); + } + virtual ~AnyCollectionProxy() { } +}; +#endif +#endif diff --git a/cont/inc/TGenCollectionStreamer.h b/cont/inc/TGenCollectionStreamer.h new file mode 100644 index 00000000000..862ffaca353 --- /dev/null +++ b/cont/inc/TGenCollectionStreamer.h @@ -0,0 +1,89 @@ +// @(#)root/cont:$Name: $:$Id: TGenCollectionStreamer.h,v 1.15 2004/10/13 15:30:22 rdm 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_TGenCollectionStreamer +#define ROOT_TGenCollectionStreamer + +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionStreamer +// +// Streamer around an arbitrary STL like container, which implements basic +// container functionality. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionProxy.h" + +class TGenCollectionStreamer : public TGenCollectionProxy { + +protected: + /// Stream I/O: Map input streamer + void ReadMap(int nElements, TBuffer &b); + /// Stream I/O: Object input streamer + void ReadObjects(int nElements, TBuffer &b); + /// Stream I/O: Primitive input streamer + void ReadPrimitives(int nElements, TBuffer &b); + /// Stream I/O: Map output streamer + void WriteMap(int nElements, TBuffer &b); + /// Stream I/O: Object output streamer + void WriteObjects(int nElements, TBuffer &b); + /// Stream I/O: Primitive output streamer + void WritePrimitives(int nElements, TBuffer &b); + +public: + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TGenCollectionStreamer(const TGenCollectionStreamer& copy); + + /// Initializing constructor + TGenCollectionStreamer(Info_t typ, size_t iter_size); + + /// Standard destructor + virtual ~TGenCollectionStreamer(); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &buff, void *pObj, int siz) { + TGenCollectionProxy::Streamer(buff, pObj, siz); + } +}; + +template <typename T> +struct AnyCollectionStreamer : public TGenCollectionStreamer { + AnyCollectionStreamer() + : TGenCollectionStreamer(typeid(T::Cont_t),sizeof(T::Iter_t)) { + fValDiff = sizeof(T::Value_t); + fValOffset = T::value_offset(); + fSize.call = T::size; + fFirst.call = T::first; + fNext.call = T::next; + fClear.call = T::clear; + fResize.call = T::resize; + fCollect.call = T::collect; + fConstruct.call = T::construct; + fDestruct.call = T::destruct; + fFeed.call = T::feed; + CheckFunctions(); + } + virtual ~AnyCollectionStreamer() { } +}; + +// Forward declaration in the event of later seperation +typedef TGenCollectionStreamer TGenMapStreamer; + +#endif +#endif diff --git a/cont/inc/TVectorProxy.h b/cont/inc/TVectorProxy.h index 8f58b886fbf..40c89412a55 100644 --- a/cont/inc/TVectorProxy.h +++ b/cont/inc/TVectorProxy.h @@ -1,4 +1,4 @@ -// @(#)root/cont:$Name: $:$Id: TVectorProxy.h,v 1.10 2004/10/07 17:08:53 brun Exp $ +// @(#)root/cont:$Name: $:$Id: TVectorProxy.h,v 1.11 2004/10/08 15:19:37 brun Exp $ // Author: Philippe Canal 20/08/2003 /************************************************************************* @@ -230,9 +230,12 @@ namespace ROOT { TClass *GetValueClass() { return 0; } Bool_t HasPointers() const { return 0; } void Resize(UInt_t n, Bool_t ) { fProxied->resize(n); } + virtual void* Allocate(UInt_t n, Bool_t forceDelete) { fProxied->resize(n); return 0; } + virtual void Commit(void*) {} UInt_t Size() const { return fProxied ? (*fProxied).size() : 0; } void Streamer(TBuffer &b) { GetCollectionClass()->Streamer( fProxied, b ); } + }; diff --git a/cont/inc/TVirtualCollectionProxy.h b/cont/inc/TVirtualCollectionProxy.h index 1bcd15cdd0d..b8bbf86d634 100644 --- a/cont/inc/TVirtualCollectionProxy.h +++ b/cont/inc/TVirtualCollectionProxy.h @@ -1,4 +1,4 @@ -// @(#)root/cont:$Name: $:$Id: TVirtualCollectionProxy.h,v 1.5 2004/10/07 17:15:13 brun Exp $ +// @(#)root/cont:$Name: $:$Id: TVirtualCollectionProxy.h,v 1.6 2004/10/08 15:19:37 brun Exp $ // Author: Philippe Canal 20/08/2003 /************************************************************************* @@ -9,8 +9,8 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -#ifndef Root_TVirtualCollectionProxy_h -#define Root_TVirtualCollectionProxy_h +#ifndef Root_TVirtualCollectionProxy +#define Root_TVirtualCollectionProxy ////////////////////////////////////////////////////////////////////////// // // @@ -69,9 +69,10 @@ public: virtual void Clear(const char *opt = "") = 0; // Clear the container virtual void Resize(UInt_t n, Bool_t forceDelete) = 0; // Resize the container virtual UInt_t Size() const = 0; // Return the current size of the container - + virtual void* Allocate(UInt_t n, Bool_t forceDelete) = 0; + virtual void Commit(void*) = 0; virtual void Streamer(TBuffer &b) = 0; // Stream the proxied container char *operator[](UInt_t idx) const { return (char*)(const_cast<TVirtualCollectionProxy*>(this))->At(idx); } }; -#endif // Root_TVirtualCollectionProxy_h +#endif diff --git a/cont/src/TCollectionProxy.cxx b/cont/src/TCollectionProxy.cxx new file mode 100644 index 00000000000..a065b3c4963 --- /dev/null +++ b/cont/src/TCollectionProxy.cxx @@ -0,0 +1,273 @@ +// @(#)root/cont:$Name: $:$Id: TCollectionProxy.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionProxy +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TError.h" +#include "TClassEdit.h" +#include "TCollectionProxy.h" +#include "TGenCollectionProxy.h" +#include "TGenCollectionStreamer.h" + +#include "TEmulatedMapProxy.h" +#include "TEmulatedCollectionProxy.h" + +static TClassEdit::ESTLType stl_type(const char* class_name) { + if ( class_name ) { + int nested = 0; + std::vector<std::string> inside; + int num = TClassEdit::GetSplit(class_name,inside,nested); + if ( num > 1 ) { + return (TClassEdit::ESTLType)TClassEdit::STLKind(inside[0].c_str()); + } + } + return TClassEdit::kNotSTL; +} + +/// Generate emulated collection proxy for a given class +TCollectionProxy::Proxy_t* +TCollectionProxy::genEmulatedProxy(const char* class_name) +{ + switch ( stl_type(class_name) ) { + case TClassEdit::kNotSTL: + return 0; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + return new TEmulatedMapProxy(class_name); + default: + return new TEmulatedCollectionProxy(class_name); + } + return 0; +} + +/// Generate emulated class streamer for a given collection class +TClassStreamer* +TCollectionProxy::genEmulatedClassStreamer(const char* class_name) +{ + TCollectionClassStreamer* s = new TCollectionClassStreamer(); + s->AdoptProxy(genEmulatedProxy(class_name)); + return s; +} + +/// Generate emulated member streamer for a given collection class +TMemberStreamer* +TCollectionProxy::genEmulatedMemberStreamer(const char* class_name) +{ + TCollectionMemberStreamer* s = new TCollectionMemberStreamer(); + s->AdoptProxy(genEmulatedProxy(class_name)); + return s; +} + +/// Generate proxy from static functions +TCollectionProxy::Proxy_t* +TCollectionProxy::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*) + ) +{ + TGenCollectionProxy* ptr = new TGenCollectionProxy(info, iter_size); + ptr->fValDiff = value_diff; + ptr->fValOffset = value_offset; + ptr->fSize.call = size_func; + ptr->fResize.call = resize_func; + ptr->fNext.call = next_func; + ptr->fFirst.call = first_func; + ptr->fClear.call = clear_func; + ptr->fConstruct.call = construct_func; + ptr->fDestruct.call = destruct_func; + ptr->fFeed.call = feed_func; + ptr->fCollect.call = collect_func; + ptr->CheckFunctions(); + return ptr; +} + +/// Generate streamer from static functions +TCollectionProxy::Proxy_t* +TCollectionProxy::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*) + ) +{ + TGenCollectionStreamer* ptr = new TGenCollectionStreamer(info, iter_size); + ptr->fValDiff = value_diff; + ptr->fValOffset = value_offset; + ptr->fSize.call = size_func; + ptr->fResize.call = resize_func; + ptr->fNext.call = next_func; + ptr->fFirst.call = first_func; + ptr->fClear.call = clear_func; + ptr->fConstruct.call = construct_func; + ptr->fDestruct.call = destruct_func; + ptr->fFeed.call = feed_func; + ptr->fCollect.call = collect_func; + ptr->CheckFunctions(); + return ptr; +} + +/// Generate class streamer from static functions +TClassStreamer* +TCollectionProxy::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*) + ) +{ + TCollectionClassStreamer* s = new TCollectionClassStreamer(); + s->AdoptProxy(genExplicitStreamer(info, + iter_size, + value_diff, + value_offset, + size_func, + resize_func, + clear_func, + first_func, + next_func, + construct_func, + destruct_func, + feed_func, + collect_func)); + return s; +} + +/// Generate member streamer from static functions +TMemberStreamer* +TCollectionProxy::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*) + ) +{ + TCollectionMemberStreamer* s = new TCollectionMemberStreamer(); + s->AdoptProxy(genExplicitStreamer(info, + iter_size, + value_diff, + value_offset, + size_func, + resize_func, + clear_func, + first_func, + next_func, + construct_func, + destruct_func, + feed_func, + collect_func)); + return s; +} + +/// Issue Error about invalid proxy +void TCollectionStreamer::InvalidProxyError() { + Fatal("TCollectionStreamer>","No proxy available. Data streaming impossible."); +} + +/// Initializing constructor +TCollectionStreamer::TCollectionStreamer() : fProxy(0) { +} + +/// Copy constructor +TCollectionStreamer::TCollectionStreamer(const TCollectionStreamer& c) { + if ( c.fProxy ) { + fProxy = c.fProxy->Generate(); + return; + } + InvalidProxyError(); +} + +/// Standard destructor +TCollectionStreamer::~TCollectionStreamer() { + if ( fProxy ) { + delete fProxy; + } +} + +/// Attach worker proxy +void TCollectionStreamer::AdoptProxy(TVirtualCollectionProxy* proxy) { + if ( fProxy ) { + delete fProxy; + } + fProxy = proxy; +} + +/// Streamer for I/O handling +void TCollectionStreamer::Streamer(TBuffer &buff, void *pObj, int /* siz */ ) { + if ( fProxy ) { + TVirtualCollectionProxy::TPushPop env(fProxy, pObj); + fProxy->Streamer(buff); + return; + } + InvalidProxyError(); +} +#ifdef _WIN32 +#include <vector> +#include <list> +#include <deque> +#include <set> +#include <map> +void __test() { + TCollectionProxy::genProxy<TCollectionProxy::Pushback<std::vector<bool> > >(); + TCollectionProxy::genProxy<TCollectionProxy::Pushback<std::list<bool> > >(); + TCollectionProxy::genProxy<TCollectionProxy::Pushback<std::deque<bool> > >(); + TCollectionProxy::genProxy<TCollectionProxy::Insert<std::set<bool> > >(); + TCollectionProxy::genProxy<TCollectionProxy::MapInsert<std::map<bool,bool> > >(); +} +#endif diff --git a/cont/src/TEmulatedCollectionProxy.cxx b/cont/src/TEmulatedCollectionProxy.cxx new file mode 100644 index 00000000000..834d5ca9762 --- /dev/null +++ b/cont/src/TEmulatedCollectionProxy.cxx @@ -0,0 +1,437 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedCollectionProxy.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedCollectionProxy +// +// Streamer around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TEmulatedCollectionProxy.h" +#include "TStreamerInfo.h" +#include "TClassEdit.h" +#include "TError.h" +#include "TROOT.h" +#include <iostream> + +/// Build a Streamer for an emulated vector whose type is 'name'. +TEmulatedCollectionProxy::TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy) +: TGenCollectionProxy(copy) +{ +} + +/// Build a Streamer for a collection whose type is described by 'collectionClass'. +TEmulatedCollectionProxy::TEmulatedCollectionProxy(const char* cl_name) +: TGenCollectionProxy(typeid(std::vector<char>), sizeof(std::vector<char>::iterator)) +{ + fName = cl_name; + Initialize(); +} + +/// Standard destructor +TEmulatedCollectionProxy::~TEmulatedCollectionProxy() { +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TEmulatedCollectionProxy::Generate() const { + if ( !fClass ) Initialize(); + return new TEmulatedCollectionProxy(*this); +} + +/// Proxy initializer +TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx() { + fClass = gROOT->GetClass(fName.c_str()); + fEnv = 0; + fKey = 0; + if ( fClass ) { + int nested = 0; + std::vector<std::string> inside; + fPointers = false; + int num = TClassEdit::GetSplit(fName.c_str(),inside,nested); + if ( num > 1 ) { + std::string nam; + fSTL_type = TClassEdit::STLKind(inside[0].c_str()); + // std::cout << "Initialized " << typeid(*this).name() << ":" << fName << std::endl; + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + fKey = new Value(inside[1]); + fVal = new Value(inside[2]); + fPointers |= 0 != (fKey->fCase&G__BIT_ISPOINTER); + if ( 0 == fValDiff ) { + fValDiff = fKey->fSize + fVal->fSize; + } + if ( 0 == fValOffset ) { + fValOffset = fKey->fSize; + } + break; + default: + fVal = new Value(inside[1]); + if ( 0 == fValDiff ) { + fValDiff = fVal->fSize; + } + break; + } + fValue = new Value(*fVal); + fPointers |= 0 != (fVal->fCase&G__BIT_ISPOINTER); + return this; + } + Fatal("TEmulatedCollectionProxy","Components of %s not analysed!",fClass->GetName()); + } + Fatal("TEmulatedCollectionProxy","Collection class %s not found!",fTypeinfo.name()); + return 0; +} + +/// Return the current size of the container +UInt_t TEmulatedCollectionProxy::Size() const { + if ( fEnv && fEnv->object ) { + return fEnv->size = PCont_t(fEnv->object)->size()/fValDiff; + } + Fatal("TEmulatedCollectionProxy","Size> Logic error - no proxy object set."); + return 0; +} + +/// Clear the emulated collection. +void TEmulatedCollectionProxy::Clear(const char* opt) { + Resize(0, opt && *opt=='f'); +} + +/// Shrink the container +void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t /* force */ ) { + typedef std::string String_t; + PCont_t c = PCont_t(fEnv->object); + char* addr = ((char*)fEnv->start) + fValDiff*left; + size_t i; + + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + addr = ((char*)fEnv->start) + fValDiff*left; + switch(fKey->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i= fKey->fType ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) { + // Call emulation in case non-compiled content + fKey->fDtor ? (*fKey->fDtor)(addr) : fKey->fType->Destructor(addr, kTRUE); + } + break; + case R__BIT_ISSTRING: + for( i=left; i<nCurr; ++i, addr += fValDiff ) + ((std::string*)addr)->~String_t(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + for( i=left; i<nCurr; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + void* ptr = i->ptr(); + if ( fKey->fDelete ) { // Case of compiled content + (*fKey->fDelete)(ptr); + } + else if ( fKey->fType ) { // Case of emulated content + fKey->fType->Destructor(ptr); + } + else if ( fKey->fDtor ) { // Case of compiled content + (*fKey->fDtor)(ptr); + ::operator delete(ptr); + } + else { + ::operator delete(i->ptr()); + } + i->set(0); + } + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete (std::string*)i; + i->set(0); + } + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete i->tstr; + i->set(0); + } + break; + } + addr = ((char*)fEnv->start)+fKey->fSize+fValDiff*left; + // DO NOT break; just continue + + // General case for all values + default: + switch( fVal->fCase ) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i=fVal->fDtor ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) { + // Call emulation in case non-compiled content + fKey->fDtor ? (*fKey->fDtor)(addr) : fKey->fType->Destructor(addr,kTRUE); + } + break; + case R__BIT_ISSTRING: + for( i=left; i<nCurr; ++i, addr += fValDiff ) + ((std::string*)addr)->~String_t(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + for( i=left; i<nCurr; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + void* p = i->ptr(); + if ( p ) { + if ( fVal->fDelete ) { // Case of compiled content + (*fVal->fDelete)(p); + } + else if ( fVal->fType ) { // Case of emultated content + fVal->fType->Destructor(p); + } + else if ( fVal->fDtor ) { // Case of compiled content + (*fVal->fDtor)(p); + ::operator delete(p); + } + else { + ::operator delete(p); + } + } + i->set(0); + } + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete (std::string*)i; + i->set(0); + } + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete i->tstr; + i->set(0); + } + break; + } + } + c->resize(left*fValDiff,0); + fEnv->start = left>0 ? &(*c->begin()) : 0; + return; +} + +/// Expand the container +void TEmulatedCollectionProxy::Expand(UInt_t nCurr, UInt_t left) { + size_t i; + PCont_t c = PCont_t(fEnv->object); + c->resize(left*fValDiff,0); + fEnv->start = left>0 ? &(*c->begin()) : 0; + char* addr = ((char*)fEnv->start) + fValDiff*nCurr; + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + switch(fKey->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i=fVal->fCtor ? nCurr : left; i<left; ++i, addr += fValDiff ) + (*fKey->fCtor)(addr); + break; + case R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + ::new(addr) std::string(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + *(void**)addr = 0; + break; + } + addr = ((char*)fEnv->start)+fKey->fSize+fValDiff*nCurr; + // DO NOT break; just continue + + // General case for all values + default: + switch(fVal->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i=fVal->fCtor ? nCurr : left; i<left; ++i, addr += fValDiff ) + (*fVal->fCtor)(addr); + break; + case R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + ::new(addr) std::string(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + *(void**)addr = 0; + break; + } + break; + } +} +/// Resize the container +void TEmulatedCollectionProxy::Resize(UInt_t left, Bool_t force) { + if ( fEnv && fEnv->object ) { + size_t nCurr = Size(); + PCont_t c = PCont_t(fEnv->object); + fEnv->start = left>0 ? &(*c->begin()) : 0; + if ( left == nCurr ) { + return; + } + else if ( left < nCurr ) { + Shrink(nCurr, left, force); + return; + } + Expand(nCurr, left); + return; + } + Fatal("TEmulatedCollectionProxy","Resize> Logic error - no proxy object set."); +} + +/// Return the address of the value at index 'idx' +void* TEmulatedCollectionProxy::At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + PCont_t c = PCont_t(fEnv->object); + return idx<(c->size()/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0; + } + Fatal("TEmulatedCollectionProxy","At> Logic error - no proxy object set."); + return 0; +} + +void* TEmulatedCollectionProxy::Allocate(UInt_t n, Bool_t forceDelete) { + Resize(n, forceDelete); + return fEnv; +} + +void TEmulatedCollectionProxy::Commit(void* /* env */ ) { +} + +/// Object input streamer +void TEmulatedCollectionProxy::ReadItems(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + StreamHelper* itm = (StreamHelper*)At(0); + switch (fVal->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(fVal->fKind) ) { + case kChar_t: b.ReadFastArray(&itm->s_char , nElements); break; + case kShort_t: b.ReadFastArray(&itm->s_short , nElements); break; + case kInt_t: b.ReadFastArray(&itm->s_int , nElements); break; + case kLong_t: b.ReadFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.ReadFastArray(&itm->flt , nElements); break; + case kDouble_t: b.ReadFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.ReadFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.ReadFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.ReadFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.ReadFastArray(&itm->u_int , nElements); break; + case kULong_t: b.ReadFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind); + } + break; +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fVal->fType) ); + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->read_any_object(fVal,b) ); + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ); +#endif + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ); + } +#undef DOLOOP +} + +/// Object output streamer +void TEmulatedCollectionProxy::WriteItems(int nElements, TBuffer &b) { + StreamHelper* itm = (StreamHelper*)At(0); + switch (fVal->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + itm = (StreamHelper*)At(0); + switch( int(fVal->fKind) ) { + case kChar_t: b.WriteFastArray(&itm->s_char , nElements); break; + case kShort_t: b.WriteFastArray(&itm->s_short , nElements); break; + case kInt_t: b.WriteFastArray(&itm->s_int , nElements); break; + case kLong_t: b.WriteFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.WriteFastArray(&itm->flt , nElements); break; + case kDouble_t: b.WriteFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.WriteFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.WriteFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.WriteFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.WriteFastArray(&itm->u_int , nElements); break; + case kULong_t: b.WriteFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind); + } + break; +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fVal->fType) ); + case R__BIT_ISSTRING: + DOLOOP( TString(i->c_str()).Streamer(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) ); + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + DOLOOP( i->write_std_string_pointer(b) ); +#endif + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + DOLOOP( i->write_tstring_pointer(b) ); + } +#undef DOLOOP +} + +/// TClassStreamer IO overload +void TEmulatedCollectionProxy::Streamer(TBuffer &b) { + if ( b.IsReading() ) { //Read mode + int nElements = 0; + b >> nElements; + if ( fEnv->object ) { + Resize(nElements,true); + } + if ( nElements > 0 ) { + ReadItems(nElements, b); + } + } + else { // Write case + int nElements = fEnv->object ? *(size_t*)fSize.invoke(fEnv) : 0; + b << nElements; + if ( nElements > 0 ) { + WriteItems(nElements, b); + } + } +} diff --git a/cont/src/TEmulatedMapProxy.cxx b/cont/src/TEmulatedMapProxy.cxx new file mode 100644 index 00000000000..e591582e010 --- /dev/null +++ b/cont/src/TEmulatedMapProxy.cxx @@ -0,0 +1,221 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedMapProxy.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedMapProxy +// +// Streamer around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TEmulatedMapProxy.h" +#include "TStreamerInfo.h" +#include "TClassEdit.h" +#include "TError.h" + +/// Build a Streamer for an emulated vector whose type is 'name'. +TEmulatedMapProxy::TEmulatedMapProxy(const TEmulatedMapProxy& copy) +: TEmulatedCollectionProxy(copy) +{ + if ( !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap) ) { + Fatal("TEmulatedMapProxy","Class %s is not a map-type!",fName.c_str()); + } +} + +/// Build a Streamer for a collection whose type is described by 'collectionClass'. +TEmulatedMapProxy::TEmulatedMapProxy(const char* cl_name) +: TEmulatedCollectionProxy(cl_name) +{ + fName = cl_name; + Initialize(); + if ( !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap) ) { + Fatal("TEmulatedMapProxy","Class %s is not a map-type!",fName.c_str()); + } +} + +/// Standard destructor +TEmulatedMapProxy::~TEmulatedMapProxy() { +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TEmulatedMapProxy::Generate() const { + if ( !fClass ) Initialize(); + return new TEmulatedMapProxy(*this); +} + +/// Return the address of the value at index 'idx' +void* TEmulatedMapProxy::At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + PCont_t c = PCont_t(fEnv->object); + return idx<(c->size()/fValDiff) ? ((char*)&(*c->begin())) + idx*fValDiff : 0; + } + Fatal("TEmulatedMapProxy","At> Logic error - no proxy object set."); + return 0; +} + +/// Return the current size of the container +UInt_t TEmulatedMapProxy::Size() const { + if ( fEnv && fEnv->object ) { + PCont_t c = PCont_t(fEnv->object); + return fEnv->size = (c->size()/fValDiff); + } + Fatal("TEmulatedMapProxy","Size> Logic error - no proxy object set."); + return 0; +} + +/// Map input streamer +void TEmulatedMapProxy::ReadMap(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + int idx, loop, off[2] = {0, fKey->fSize }; + Value *v, *val[2] = { fKey, fVal }; + StreamHelper* helper; + float f; + char* addr = 0; + char* temp = (char*)At(0); + for ( idx = 0; idx < nElements; ++idx ) { + addr = temp + idx*fValDiff; + for ( loop=0; loop<2; loop++) { + addr += off[loop]; + helper = (StreamHelper*)addr; + v = val[loop]; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b >> helper->s_char; break; + case kShort_t: b >> helper->s_short; break; + case kInt_t: b >> helper->s_int; break; + case kLong_t: b >> helper->s_long; break; + case kLong64_t: b >> helper->s_longlong; break; + case kFloat_t: b >> helper->flt; break; + case kDouble_t: b >> helper->dbl; break; + case kBOOL_t: b >> helper->boolean; break; + case kUChar_t: b >> helper->u_char; break; + case kUShort_t: b >> helper->u_short; break; + case kUInt_t: b >> helper->u_int; break; + case kULong_t: b >> helper->u_long; break; + case kULong64_t: b >> helper->u_longlong; break; + case kDouble32_t:b >> f; + helper->dbl = double(f); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedMapProxy","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(helper,v->fType); + break; + case R__BIT_ISSTRING: + helper->read_std_string(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + helper->set(b.ReadObjectAny(v->fType)); + break; + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + helper->read_std_string_pointer(b); +#endif + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + helper->read_tstring_pointer(vsn3,b); + break; + } + } + } +} + +/// Map output streamer +void TEmulatedMapProxy::WriteMap(int nElements, TBuffer &b) { + Value *v, *val[2] = { fKey, fVal }; + int off[2] = { 0, fKey->fSize }; + StreamHelper* i; + char* addr = 0; + char* temp = (char*)At(0); + for (int loop, idx = 0; idx < nElements; ++idx ) { + addr = temp + idx*fValDiff; + for ( loop = 0; loop<2; ++loop ) { + addr += off[loop]; + i = (StreamHelper*)addr; + v = val[loop]; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b << i->s_char; break; + case kShort_t: b << i->s_short; break; + case kInt_t: b << i->s_int; break; + case kLong_t: b << i->s_long; break; + case kLong64_t: b << i->s_longlong; break; + case kFloat_t: b << i->flt; break; + case kDouble_t: b << i->dbl; break; + case kBOOL_t: b << i->boolean; break; + case kUChar_t: b << i->u_char; break; + case kUShort_t: b << i->u_short; break; + case kUInt_t: b << i->u_int; break; + case kULong_t: b << i->u_long; break; + case kULong64_t: b << i->u_longlong; break; + case kDouble32_t:b << float(i->dbl); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedMapProxy","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(i,v->fType); + break; + case R__BIT_ISSTRING: + TString(i->c_str()).Streamer(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + b.WriteObjectAny(i->ptr(),v->fType); + break; + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + i->write_std_string_pointer(b); +#endif + break; + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + i->write_tstring_pointer(b); + break; + } + } + } +} + +/// TClassStreamer IO overload +void TEmulatedMapProxy::Streamer(TBuffer &b) { + if ( b.IsReading() ) { //Read mode + int nElements = 0; + b >> nElements; + if ( fEnv->object ) { + Resize(nElements,true); + } + if ( nElements > 0 ) { + ReadMap(nElements, b); + } + } + else { // Write case + int nElements = fEnv->object ? Size() : 0; + b << nElements; + if ( nElements > 0 ) { + WriteMap(nElements, b); + } + } +} diff --git a/cont/src/TGenCollectionProxy.cxx b/cont/src/TGenCollectionProxy.cxx new file mode 100644 index 00000000000..97e3dfa76b9 --- /dev/null +++ b/cont/src/TGenCollectionProxy.cxx @@ -0,0 +1,714 @@ +// @(#)root/cont:$Name: $:$Id: TGenVectorProxy.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionProxy +// +// Proxy around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionProxy.h" +#include "TStreamerElement.h" +#include "TClassEdit.h" +#include "Property.h" +#include "TClass.h" +#include "TError.h" +#include "TROOT.h" +#include "Api.h" +#include <iostream> + +#define MESSAGE(which,text) + +/** @class TGenVectorProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenVectorProxy : public TGenCollectionProxy { +public: + /// Standard Destructor + TGenVectorProxy(const TGenCollectionProxy& c) : TGenCollectionProxy(c) { + } + /// Standard Destructor + virtual ~TGenVectorProxy() { + } + /// Return the address of the value at index 'idx' + virtual void* At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + fEnv->idx = idx; + switch( idx ) { + case 0: + return fEnv->start = fFirst.invoke(fEnv); + default: + return ((char*)fEnv->start) + fValDiff*idx; + } + } + Fatal("TGenVectorProxy","At> Logic error - no proxy object set."); + return 0; + } + /// Call to delete/destruct individual item + virtual void DeleteItem(bool force, void* ptr) const { + if ( force && ptr ) { + if ( fValue->fDelete ) { + (*fValue->fDelete)(ptr); + } + else if ( fVal->fType ) { + fVal->fType->Destructor(ptr); + } + else { + ::operator delete(ptr); + } + } + } +}; + +/** @class TGenListProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenListProxy : public TGenVectorProxy { +public: + /// Standard Destructor + TGenListProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c) { + } + /// Standard Destructor + virtual ~TGenListProxy() { + } + /// Return the address of the value at index 'idx' + void* At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + switch( idx ) { + case 0: + fEnv->idx = idx; + return fEnv->start = fFirst.invoke(fEnv); + default: { + fEnv->idx = idx - fEnv->idx; + void* result = fNext.invoke(fEnv); + fEnv->idx = idx; + return result; + } + } + } + Fatal("TGenListProxy","At> Logic error - no proxy object set."); + return 0; + } +}; + +/** @class TGenSetProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenSetProxy : public TGenVectorProxy { +public: + /// Standard Destructor + TGenSetProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c) { + } + /// Standard Destructor + virtual ~TGenSetProxy() { + } + /// Return the address of the value at index 'idx' + void* At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + if ( fEnv->temp ) { + return (((char*)fEnv->temp)+idx*fValDiff); + } + switch( idx ) { + case 0: + fEnv->idx = idx; + return fEnv->start = fFirst.invoke(fEnv); + default: { + fEnv->idx = idx - fEnv->idx; + void* result = fNext.invoke(fEnv); + fEnv->idx = idx; + return result; + } + } + } + Fatal("TGenSetProxy","At> Logic error - no proxy object set."); + return 0; + } +}; + +/** @class TGenMapProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenMapProxy : public TGenSetProxy { +public: + /// Standard Destructor + TGenMapProxy(const TGenCollectionProxy& c) : TGenSetProxy(c) { + } + /// Standard Destructor + virtual ~TGenMapProxy() { + } + /// Call to delete/destruct individual item + virtual void DeleteItem(bool /* force */, void* ptr) const { + if ( fKey->fCase&G__BIT_ISPOINTER ) { + if ( *(void**)ptr ) { + (*fKey->fDelete)(*(void**)ptr); + } + } + if ( fVal->fCase&G__BIT_ISPOINTER ) { + char *addr = ((char*)ptr)+fKey->fSize; + if ( *(void**)addr ) (*fVal->fDelete)(*(void**)addr); + } + } +}; + +TGenCollectionProxy::Value::Value(const Value& copy) { + fType = copy.fType; + fCase = copy.fCase; + fKind = copy.fKind; + fSize = copy.fSize; + fCtor = copy.fCtor; + fDtor = copy.fDtor; + fDelete = copy.fDelete; +} + +TGenCollectionProxy::Value::Value(const std::string& inside) { + fType = 0; + fCase = 0; + fCtor = 0; + fDtor = 0; + fDelete = 0; + fSize = std::string::npos; + fKind = kNoType_t; + std::string intype = TClassEdit::ShortType(inside.c_str(),TClassEdit::kDropTrailStar ); + if ( inside.substr(0,6) == "string" || inside.substr(0,11) == "std::string" ) { + fCase = R__BIT_ISSTRING; + fType = gROOT->GetClass("string"); + fCtor = fType->GetNew(); + fDtor = fType->GetDestructor(); + fDelete = fType->GetDelete(); + switch(inside[inside.length()-1]) { + case '*': + fCase |= G__BIT_ISPOINTER; + fSize = sizeof(void*); + break; + default: + fSize = sizeof(std::string); + break; + } + } + else { + G__TypeInfo ti(inside.c_str()); + if ( !ti.IsValid() ) { + if (intype != inside) { + fCase |= G__BIT_ISPOINTER; + fSize = sizeof(void*); + } + fType = gROOT->GetClass(intype.c_str()); + if (fType) { + fCase |= G__BIT_ISCLASS; + fCtor = fType->GetNew(); + fDtor = fType->GetDestructor(); + fDelete = fType->GetDelete(); + } + else { + // either we have an Emulated enum or a really unknown class! + // let's just claim its an enum :( + fCase = G__BIT_ISENUM; + fSize = sizeof(Int_t); + fKind = kInt_t; + } + } + else { + long P = ti.Property(); + if ( P&G__BIT_ISPOINTER ) { + fSize = sizeof(void*); + } + if ( P&G__BIT_ISSTRUCT ) { + P |= G__BIT_ISCLASS; + } + if ( P&G__BIT_ISCLASS ) { + fType = gROOT->GetClass(intype.c_str()); + Assert(fType); + fCtor = fType->GetNew(); + fDtor = fType->GetDestructor(); + fDelete = fType->GetDelete(); + } + else if ( P&G__BIT_ISFUNDAMENTAL ) { + TDataType *fundType = gROOT->GetType( intype.c_str() ); + fKind = (EDataType)fundType->GetType(); + fSize = ti.Size(); + Assert(fKind>0 && fKind<20); + } + else if ( P&G__BIT_ISENUM ) { + fSize = sizeof(int); + fKind = kInt_t; + } + fCase = P & (G__BIT_ISPOINTER|G__BIT_ISFUNDAMENTAL|G__BIT_ISENUM|G__BIT_ISCLASS); + if (fType == TString::Class() && (fCase&G__BIT_ISPOINTER)) { + fCase |= R__BIT_ISTSTRING; + } + } + } + if ( fSize == std::string::npos ) { + if ( fType == 0 ) { + Fatal("TGenCollectionProxy","Could not find %s!",inside.c_str()); + } + fSize = fType->Size(); + } +} + +/// Build a proxy for an emulated container. +TGenCollectionProxy::TGenCollectionProxy(const TGenCollectionProxy& copy) +: TVirtualCollectionProxy(copy.fClass), + fTypeinfo(copy.fTypeinfo) +{ + fEnv = 0; + fName = copy.fName; + fPointers = copy.fPointers; + fSTL_type = copy.fSTL_type; + fSize.call = copy.fSize.call; + fNext.call = copy.fNext.call; + fFirst.call = copy.fFirst.call; + fClear.call = copy.fClear.call; + fResize.call = copy.fResize.call; + fDestruct.call = copy.fDestruct.call; + fConstruct.call = copy.fConstruct.call; + fFeed.call = copy.fFeed.call; + fCollect.call = copy.fCollect.call; + fValOffset = copy.fValOffset; + fValDiff = copy.fValDiff; + fValue = copy.fValue ? new Value(*copy.fValue) : 0; + fVal = copy.fVal ? new Value(*copy.fVal) : 0; + fKey = copy.fKey ? new Value(*copy.fKey) : 0; +} + +/// Build a proxy for a collection whose type is described by 'collectionClass'. +TGenCollectionProxy::TGenCollectionProxy(Info_t info, size_t iter_size) +: TVirtualCollectionProxy(0), + fTypeinfo(info) +{ + fEnv = 0; + fSize.call = 0; + fFirst.call = 0; + fNext.call = 0; + fClear.call = 0; + fResize.call = 0; + fDestruct.call = 0; + fConstruct.call = 0; + fCollect.call = 0; + fFeed.call = 0; + fValue = 0; + fKey = 0; + fVal = 0; + fValOffset = 0; + fValDiff = 0; + fPointers = false; + Env_t e; + if ( iter_size > sizeof(e.buff) ) { + Fatal("TGenCollectionProxy", + "%s %s are too large:%d bytes. Maximum is:%d bytes", + "Iterators for collection", + fClass->GetName(), + iter_size, + sizeof(e.buff)); + } +} + +/// Standard destructor +TGenCollectionProxy::~TGenCollectionProxy() { + for(Proxies_t::iterator i=fProxyList.begin(); i != fProxyList.end(); ++i) { + if ( (*i) ) delete (*i); + } + fProxyList.clear(); + if ( fValue ) delete fValue; + if ( fVal ) delete fVal; + if ( fKey ) delete fKey; +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TGenCollectionProxy::Generate() const { + if ( !fClass ) Initialize(); + switch(fSTL_type) { + case TClassEdit::kVector: + return new TGenVectorProxy(*this); + case TClassEdit::kList: + return new TGenListProxy(*this); + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + return new TGenMapProxy(*this); + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + return new TGenSetProxy(*this); + default: + return new TGenCollectionProxy(*this); + } +} + +/// Proxy initializer +TGenCollectionProxy *TGenCollectionProxy::Initialize() const { + TGenCollectionProxy* p = const_cast<TGenCollectionProxy*>(this); + if ( fClass ) return p; + return p->InitializeEx(); +} + +/// Check existence of function pointers +void TGenCollectionProxy::CheckFunctions() const { + if ( 0 == fSize.call ) { + Fatal("TGenCollectionProxy","No 'size' function pointer for class %s present.",fName.c_str()); + } + if ( 0 == fResize.call ) { + Fatal("TGenCollectionProxy","No 'resize' function for class %s present.",fName.c_str()); + } + if ( 0 == fNext.call ) { + Fatal("TGenCollectionProxy","No 'next' function for class %s present.",fName.c_str()); + } + if ( 0 == fFirst.call ) { + Fatal("TGenCollectionProxy","No 'begin' function for class %s present.",fName.c_str()); + } + if ( 0 == fClear.call ) { + Fatal("TGenCollectionProxy","No 'clear' function for class %s present.",fName.c_str()); + } + if ( 0 == fConstruct.call ) { + Fatal("TGenCollectionProxy","No 'block constructor' function for class %s present.",fName.c_str()); + } + if ( 0 == fDestruct.call ) { + Fatal("TGenCollectionProxy","No 'block destructor' function for class %s present.",fName.c_str()); + } + if ( 0 == fFeed.call ) { + Fatal("TGenCollectionProxy","No 'data feed' function for class %s present.",fName.c_str()); + } + if ( 0 == fCollect.call ) { + Fatal("TGenCollectionProxy","No 'data collect' function for class %s present.",fName.c_str()); + } +} + +/// Proxy initializer +TGenCollectionProxy *TGenCollectionProxy::InitializeEx() { + fClass = gROOT->GetClass(fTypeinfo); + if ( fClass ) { + fEnv = 0; + fName = fClass->GetName(); + fPointers = false; + int nested = 0; + std::vector<std::string> inside; + int num = TClassEdit::GetSplit(fClass->GetName(),inside,nested); + if ( num > 1 ) { + std::string nam; + fSTL_type = TClassEdit::STLKind(inside[0].c_str()); + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + nam = "pair<"+inside[1]+","+inside[2]; + nam += (nam[nam.length()-1]=='>') ? " >" : ">"; + fValue = new Value(nam); + fVal = new Value(inside[2]); + fKey = new Value(inside[1]); + fPointers = fPointers || (0 != (fKey->fCase&G__BIT_ISPOINTER)); + if ( 0 == fValDiff ) { + fValDiff = fKey->fSize + fVal->fSize; + } + if ( 0 == fValOffset ) { + fValOffset = fKey->fSize; + } + break; + default: + fValue = new Value(inside[1]); + fVal = new Value(*fValue); + if ( 0 == fValDiff ) { + fValDiff = fVal->fSize; + } + break; + } + fPointers = fPointers || (0 != (fVal->fCase&G__BIT_ISPOINTER)); + return this; + } + Fatal("TGenCollectionProxy","Components of %s not analysed!",fClass->GetName()); + } + Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name()); + return 0; +} + +/// Return a pointer to the TClass representing the container +TClass *TGenCollectionProxy::GetCollectionClass() { + return fClass ? fClass : Initialize()->fClass; +} + +/// Return the sizeof the collection object. +UInt_t TGenCollectionProxy::Sizeof() const { + return fClass->Size(); +} + +/// Return true if the content is of type 'pointer to' +Bool_t TGenCollectionProxy::HasPointers() const { + return fPointers; +} + +/// Return a pointer to the TClass representing the content. +TClass *TGenCollectionProxy::GetValueClass() { + return fValue->fType; +} + +/// Set pointer to the TClass representing the content. +void TGenCollectionProxy::SetValueClass(TClass *new_Value_type) { + fValue->fType = new_Value_type; +} + +/// If the content is a simple numerical value, return its type (see TDataType) +EDataType TGenCollectionProxy::GetType() { + return fValue->fKind; +} + +/// Return the address of the value at index 'idx' +void* TGenCollectionProxy::At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + switch (fSTL_type) { + case TClassEdit::kVector: + fEnv->idx = idx; + switch( idx ) { + case 0: + return fEnv->start = fFirst.invoke(fEnv); + default: + return ((char*)fEnv->start) + fValDiff*idx; + } + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + if ( fEnv->temp ) { + return (((char*)fEnv->temp)+idx*fValDiff); + } + default: + switch( idx ) { + case 0: + fEnv->idx = idx; + return fEnv->start = fFirst.invoke(fEnv); + default: { + fEnv->idx = idx - fEnv->idx; + void* result = fNext.invoke(fEnv); + fEnv->idx = idx; + return result; + } + } + } + } + Fatal("TGenCollectionProxy","At> Logic error - no proxy object set."); + return 0; +} + +/// Clear the emulated collection. +void TGenCollectionProxy::Clear(const char* opt) { + if ( fEnv && fEnv->object ) { + if ( fPointers && opt && *opt=='f' ) { + size_t i, n = *(size_t*)fSize.invoke(fEnv); + if ( n > 0 ) { + for (i=0; i<n; ++i) + DeleteItem(true, TGenCollectionProxy::At(i)); + } + } + fClear.invoke(fEnv); + } +} + +/// Return the current size of the container +UInt_t TGenCollectionProxy::Size() const { + if ( fEnv && fEnv->object ) { + return *(size_t*)fSize.invoke(fEnv); + } + Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set."); + return 0; +} + +/// Resize the container +void TGenCollectionProxy::Resize(UInt_t n, Bool_t force) { + if ( fEnv && fEnv->object ) { + if ( force && fPointers ) { + size_t i, nold = *(size_t*)fSize.invoke(fEnv); + if ( n != nold ) { + for (i=n; i<nold; ++i) + DeleteItem(true, *(void**)TGenCollectionProxy::At(i)); + } + } + MESSAGE(3, "Resize(n)" ); + fEnv->size = n; + fResize.invoke(fEnv); + return; + } + Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set."); +} + +void* TGenCollectionProxy::Allocate(UInt_t n, Bool_t /* forceDelete */ ) { + if ( fEnv && fEnv->object ) { + switch ( fSTL_type ) { + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + if ( fPointers ) + Clear("force"); + else + fClear.invoke(fEnv); + ++fEnv->refCount; + fEnv->size = n; + fEnv->start = fEnv->temp = ::operator new(fValDiff*n); + fConstruct.invoke(fEnv); + return fEnv; + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + if( fPointers ) { + Clear("force"); + } + fEnv->size = n; + fResize.invoke(fEnv); + return fEnv; + } + } + return 0; +} + +void TGenCollectionProxy::Commit(void* env) { + switch (fSTL_type) { + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + return; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + if ( env ) { + Env_t* e = (Env_t*)env; + if ( e->object ) { + e->start = e->temp; + fFeed.invoke(e); + } + fDestruct.invoke(e); + e->start = 0; + --e->refCount; + } + return; + default: + return; + } +} + +void TGenCollectionProxy::PushProxy(void *objstart) { + if ( !fClass ) Initialize(); + if ( !fProxyList.empty() ) { + Env_t* back = fProxyList.back(); + if ( back->object == objstart ) { + back->refCount++; + fProxyList.push_back(back); + fEnv = back; + return; + } + } + Env_t* e = new Env_t(); + e->size = 0; + e->refCount = 1; + e->object = objstart; + e->temp = e->start = 0; + ::memset(e->buff,0,sizeof(e->buff)); + fProxyList.push_back(e); + fEnv = e; +} + +void TGenCollectionProxy::PopProxy() { + if ( !fProxyList.empty() ) { + Env_t* e = fProxyList.back(); + if ( --e->refCount <= 0 ) { + if ( e->temp ) + ::operator delete(e->temp); + delete e; + } + fProxyList.pop_back(); + } + fEnv = 0; +} + +/// Call to delete/destruct individual item +void TGenCollectionProxy::DeleteItem(bool force, void* ptr) const { + // This needs correction in the LCG dict... + // Pointers are not initialized to NULL! + if ( force && ptr ) { + switch (fSTL_type) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + if ( fKey->fCase&G__BIT_ISPOINTER ) { + if (*(void**)ptr) (*fKey->fDelete)(*(void**)ptr); + } + if ( fVal->fCase&G__BIT_ISPOINTER ) { + char *addr = ((char*)ptr)+fKey->fSize; + if (*(void**)addr) (*fVal->fDelete)(*(void**)addr); + } + // (*fValue->fDtor)(ptr); No: pair must stay intact ! + break; + default: + if ( fVal->fCase&G__BIT_ISPOINTER ) { + (*fVal->fDelete)(*(void**)ptr); + } + break; + } + } +} + +void TGenCollectionProxy::Streamer(TBuffer &buff) { + if ( fEnv ) { + GetCollectionClass()->Streamer( fEnv->object, buff ); + return; + } + Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set."); +} + +/// Streamer I/O overload +void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ ) { + TPushPop env(this, objp); + Streamer(buff); +} + +/// TClassStreamer IO overload +void TGenCollectionProxy::operator()(TBuffer &b, void *objp) { + Streamer(b, objp, 0); +} + diff --git a/cont/src/TGenCollectionStreamer.cxx b/cont/src/TGenCollectionStreamer.cxx new file mode 100644 index 00000000000..e94b36a4fbe --- /dev/null +++ b/cont/src/TGenCollectionStreamer.cxx @@ -0,0 +1,490 @@ +// @(#)root/cont:$Name: $:$Id: TGenCollectionStreamer.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionStreamer +// +// Streamer around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionStreamer.h" +#include "TStreamerInfo.h" +#include "TClassEdit.h" +#include "TError.h" +#include "TROOT.h" +#include <iostream> + +/// Build a Streamer for an emulated vector whose type is 'name'. +TGenCollectionStreamer::TGenCollectionStreamer(const TGenCollectionStreamer& copy) +: TGenCollectionProxy(copy) +{ +} + +/// Build a Streamer for a collection whose type is described by 'collectionClass'. +TGenCollectionStreamer::TGenCollectionStreamer(Info_t info, size_t iter_size) +: TGenCollectionProxy(info, iter_size) +{ +} + +/// Standard destructor +TGenCollectionStreamer::~TGenCollectionStreamer() { +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TGenCollectionStreamer::Generate() const { + if ( !fClass ) Initialize(); + return new TGenCollectionStreamer(*this); +} + +/// Primitive input streamer +void TGenCollectionStreamer::ReadPrimitives(int nElements, TBuffer &b) { + size_t len = fValDiff*nElements; + char buffer[8096]; + bool feed = false; + void* memory = 0; + StreamHelper* itm = 0; + fEnv->size = nElements; + switch ( fSTL_type ) { + case TClassEdit::kVector: + if ( fVal->fKind != EDataType(kBOOL_t) ) { + itm = (StreamHelper*)fResize.invoke(fEnv); + break; + } + default: + feed = true; + itm = (StreamHelper*)(len<sizeof(buffer) ? buffer : memory=::operator new(len)); + break; + } + fEnv->start = itm; + switch( int(fValue->fKind) ) { + case kChar_t: b.ReadFastArray(&itm->s_char , nElements); break; + case kShort_t: b.ReadFastArray(&itm->s_short , nElements); break; + case kInt_t: b.ReadFastArray(&itm->s_int , nElements); break; + case kLong_t: b.ReadFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.ReadFastArray(&itm->flt , nElements); break; + case kDouble_t: b.ReadFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.ReadFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.ReadFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.ReadFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.ReadFastArray(&itm->u_int , nElements); break; + case kULong_t: b.ReadFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",fValue->fKind); + } + if ( feed ) { // need to feed in data... + fEnv->start = fFeed.invoke(fEnv); + if ( memory ) { + ::operator delete(memory); + } + } +} + +/// Object input streamer +void TGenCollectionStreamer::ReadObjects(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + size_t len = fValDiff*nElements; + StreamHelper* itm = 0; + char buffer[8096]; + void* memory = 0; + + fEnv->size = nElements; + switch ( fSTL_type ) { + // Simple case: contiguous memory. get address of first, then jump. + case TClassEdit::kVector: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + itm = (StreamHelper*)fResize.invoke(fEnv); + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType) ); + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->set(b.ReadObjectAny(fValue->fType)) ); + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ); +#endif + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ); + } +#undef DOLOOP + break; + + // No contiguous memory, but resize is possible + // Hence accessing objects using At(i) should be not too much an overhead + case TClassEdit::kList: + case TClassEdit::kDeque: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)TGenCollectionProxy::At(idx); { x ;} ++idx;} break;} + fResize.invoke(fEnv); + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType) ); + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->set( b.ReadObjectAny(fValue->fType) ) ); + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ); +#endif + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ); + } +#undef DOLOOP + break; + + // Rather troublesome case: Objects can only be fed into the container + // Once they are created. Need to take memory from stack or heap. + case TClassEdit::kMultiSet: + case TClassEdit::kSet: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;}} + fEnv->start = itm = (StreamHelper*)(len<sizeof(buffer) ? buffer : memory=::operator new(len)); + fConstruct.invoke(fEnv); + switch ( fValue->fCase ) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType) ) + fFeed.invoke(fEnv); + fDestruct.invoke(fEnv); + break; + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ) + fFeed.invoke(fEnv); + fDestruct.invoke(fEnv); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->set(b.ReadObjectAny(fValue->fType)) ); + fFeed.invoke(fEnv); + break; + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ) + fFeed.invoke(fEnv); +#endif + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ) + fFeed.invoke(fEnv); + break; + } +#undef DOLOOP + break; + default: + break; + } + if ( memory ) { + ::operator delete(memory); + } +} + +/// Map input streamer +void TGenCollectionStreamer::ReadMap(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + size_t len = fValDiff*nElements; + Value *v; + char buffer[8096], *addr, *temp; + void* memory = 0; + StreamHelper* i; + float f; + fEnv->size = nElements; + fEnv->start = (len<sizeof(buffer) ? buffer : memory=::operator new(len)); + addr = temp = (char*)fEnv->start; + fConstruct.invoke(fEnv); + for ( int loop, idx = 0; idx < nElements; ++idx ) { + addr = temp + fValDiff*idx; + v = fKey; + for ( loop=0; loop<2; loop++ ) { + i = (StreamHelper*)addr; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b >> i->s_char; break; + case kShort_t: b >> i->s_short; break; + case kInt_t: b >> i->s_int; break; + case kLong_t: b >> i->s_long; break; + case kLong64_t: b >> i->s_longlong; break; + case kFloat_t: b >> i->flt; break; + case kDouble_t: b >> i->dbl; break; + case kBOOL_t: b >> i->boolean; break; + case kUChar_t: b >> i->u_char; break; + case kUShort_t: b >> i->u_short; break; + case kUInt_t: b >> i->u_int; break; + case kULong_t: b >> i->u_long; break; + case kULong64_t: b >> i->u_longlong; break; + case kDouble32_t:b >> f; + i->dbl = double(f); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(i,v->fType); + break; + case R__BIT_ISSTRING: + i->read_std_string(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + i->set(b.ReadObjectAny(v->fType)); + break; + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + i->read_std_string_pointer(b); +#endif + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + i->read_tstring_pointer(vsn3,b); + break; + } + v = fVal; + addr += fValOffset; + } + } + fFeed.invoke(fEnv); + fDestruct.invoke(fEnv); + if ( memory ) { + ::operator delete(memory); + } +} + +/// Primitive output streamer +void TGenCollectionStreamer::WritePrimitives(int nElements, TBuffer &b) { + size_t len = fValDiff*nElements; + char buffer[8192]; + void* memory = 0; + StreamHelper* itm = 0; + + switch ( fSTL_type ) { + case TClassEdit::kVector: + if ( fVal->fKind != EDataType(kBOOL_t) ) { + itm = (StreamHelper*)(fEnv->start = fFirst.invoke(fEnv)); + break; + } + default: + fEnv->start = itm = (StreamHelper*) (len<sizeof(buffer) ? buffer : memory=::operator new(len)); + fCollect.invoke(fEnv); + break; + } + switch( int(fValue->fKind) ) { + case kChar_t: b.WriteFastArray(&itm->s_char , nElements); break; + case kShort_t: b.WriteFastArray(&itm->s_short , nElements); break; + case kInt_t: b.WriteFastArray(&itm->s_int , nElements); break; + case kLong_t: b.WriteFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.WriteFastArray(&itm->flt , nElements); break; + case kDouble_t: b.WriteFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.WriteFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.WriteFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.WriteFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.WriteFastArray(&itm->u_int , nElements); break; + case kULong_t: b.WriteFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",fValue->fKind); + } + if ( memory ) { + ::operator delete(memory); + } +} + +/// Object output streamer +void TGenCollectionStreamer::WriteObjects(int nElements, TBuffer &b) { + StreamHelper* itm = 0; + switch(fSTL_type) { + // Simple case: contiguous memory. get address of first, then jump. + case TClassEdit::kVector: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + itm = (StreamHelper*)fFirst.invoke(fEnv); + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType)); + break; + case R__BIT_ISSTRING: + DOLOOP( TString(i->c_str()).Streamer(b)); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( b.WriteObjectAny(i->ptr(),fValue->fType) ); + break; + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + DOLOOP( i->write_std_string_pointer(b)); +#endif + break; + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + DOLOOP( i->write_tstring_pointer(b)); + break; + } +#undef DOLOOP + break; + + // No contiguous memory, but resize is possible + // Hence accessing objects using At(i) should be not too much an overhead + case TClassEdit::kList: + case TClassEdit::kDeque: + case TClassEdit::kMultiSet: + case TClassEdit::kSet: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)TGenCollectionProxy::At(idx); { x ;} ++idx;} break;} + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType)); + case R__BIT_ISSTRING: + DOLOOP( TString(i->c_str()).Streamer(b)); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( b.WriteObjectAny(i->ptr(),fValue->fType) ); + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + DOLOOP( i->write_std_string_pointer(b)); +#endif + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + DOLOOP( i->write_tstring_pointer(b)); + } +#undef DOLOOP + break; + default: + break; + } +} + +/// Map output streamer +void TGenCollectionStreamer::WriteMap(int nElements, TBuffer &b) { + StreamHelper* i; + Value *v; + + for (int loop, idx = 0; idx < nElements; ++idx ) { + char* addr = (char*)TGenCollectionProxy::At(idx); + v = fKey; + for ( loop = 0; loop<2; ++loop ) { + i = (StreamHelper*)addr; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b << i->s_char; break; + case kShort_t: b << i->s_short; break; + case kInt_t: b << i->s_int; break; + case kLong_t: b << i->s_long; break; + case kLong64_t: b << i->s_longlong; break; + case kFloat_t: b << i->flt; break; + case kDouble_t: b << i->dbl; break; + case kBOOL_t: b << i->boolean; break; + case kUChar_t: b << i->u_char; break; + case kUShort_t: b << i->u_short; break; + case kUInt_t: b << i->u_int; break; + case kULong_t: b << i->u_long; break; + case kULong64_t: b << i->u_longlong; break; + case kDouble32_t:b << float(i->dbl); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(i,v->fType); + break; + case R__BIT_ISSTRING: + TString(i->c_str()).Streamer(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + b.WriteObjectAny(i->ptr(),v->fType); + break; + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + i->write_std_string_pointer(b); +#endif + break; + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + i->write_tstring_pointer(b); + break; + } + addr += fValOffset; + v = fVal; + } + } +} + +/// TClassStreamer IO overload +void TGenCollectionStreamer::Streamer(TBuffer &b) { + if ( b.IsReading() ) { //Read mode + int nElements = 0; + b >> nElements; + if ( fEnv->object ) { + TGenCollectionProxy::Clear("force"); + } + if ( nElements > 0 ) { + switch(fSTL_type) { + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + case TClassEdit::kMultiSet: + case TClassEdit::kSet: + switch (fValue->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + ReadPrimitives(nElements, b); + return; + default: + ReadObjects(nElements, b); + return; + } + break; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + ReadMap(nElements, b); + break; + } + } + } + else { // Write case + int nElements = fEnv->object ? *(size_t*)fSize.invoke(fEnv) : 0; + b << nElements; + if ( nElements > 0 ) { + switch(fSTL_type) { + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + case TClassEdit::kMultiSet: + case TClassEdit::kSet: + switch (fValue->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + WritePrimitives(nElements, b); + return; + default: + WriteObjects(nElements, b); + return; + } + break; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + WriteMap(nElements, b); + break; + } + } + } +} diff --git a/io/inc/TEmulatedCollectionProxy.h b/io/inc/TEmulatedCollectionProxy.h new file mode 100644 index 00000000000..6df63a42a23 --- /dev/null +++ b/io/inc/TEmulatedCollectionProxy.h @@ -0,0 +1,110 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedCollectionProxy.h,v 1.15 2004/10/13 15:30:22 rdm 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_TEmulatedCollectionProxy +#define ROOT_TEmulatedCollectionProxy + +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedCollectionProxy +// +// Streamer around an arbitrary STL like container, which implements basic +// container functionality. +// +// Note: +// Although this class contains all the setup necessary to deal +// with maps, the map-like functionality is NOT supported. +// For optimization reasons this functionality is put into +// the class TEmulatedMapProxy. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionProxy.h" + +class TEmulatedCollectionProxy : public TGenCollectionProxy { + + /// Friend declaration + friend class TCollectionProxy; + +public: + /// Container type definition + typedef std::vector<char> Cont_t; + /// Pointer to container type + typedef Cont_t *PCont_t; +protected: + + /// Some hack to avoid const-ness + virtual TGenCollectionProxy* InitializeEx(); + + /// Object input streamer + void ReadItems(int nElements, TBuffer &b); + + /// Object output streamer + void WriteItems(int nElements, TBuffer &b); + + /// Shrink the container + void Shrink(UInt_t nCurr, UInt_t left, Bool_t force); + + /// Expand the container + void Expand(UInt_t nCurr, UInt_t left); + +public: + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy); + + /// Initializing constructor + TEmulatedCollectionProxy(const char* cl_name); + + /// Standard destructor + virtual ~TEmulatedCollectionProxy(); + + /// Virtual constructor + virtual void* New() const { return new Cont_t; } + + /// Virtual in-place constructor + virtual void* New(void* memory) const { return new(memory) Cont_t; } + + /// TVirtualCollectionProxy overload: Return the sizeof the collection object. + virtual UInt_t Sizeof() const { return sizeof(Cont_t); } + + /// Return the address of the value at index 'idx' + virtual void *At(UInt_t idx); + + /// Clear the container + virtual void Clear(const char *opt = ""); + + /// Resize the container + virtual void Resize(UInt_t n, Bool_t force_delete); + + /// Return the current size of the container + virtual UInt_t Size() const; + + /// Block allocation of containees + virtual void* Allocate(UInt_t n, Bool_t forceDelete); + + /// Block commit of containees + virtual void Commit(void* env); + + /// Streamer for I/O handling + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &buff, void *pObj, int siz) { + TGenCollectionProxy::Streamer(buff,pObj,siz); + } +}; + +#endif +#endif diff --git a/io/inc/TEmulatedMapProxy.h b/io/inc/TEmulatedMapProxy.h new file mode 100644 index 00000000000..43d266525c3 --- /dev/null +++ b/io/inc/TEmulatedMapProxy.h @@ -0,0 +1,66 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedMapProxy.h,v 1.15 2004/10/13 15:30:22 rdm 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_TEmulatedMapProxy +#define ROOT_TEmulatedMapProxy +#define ROOT_TGenCollectionStreamer + +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedMapProxy +// +// Streamer around an arbitrary STL like container, which implements basic +// container functionality. +// +////////////////////////////////////////////////////////////////////////// + +#include "TEmulatedCollectionProxy.h" + +class TEmulatedMapProxy : public TEmulatedCollectionProxy { + +protected: + /// Map input streamer + void ReadMap(int nElements, TBuffer &b); + + /// Map output streamer + void WriteMap(int nElements, TBuffer &b); + +public: + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TEmulatedMapProxy(const TEmulatedMapProxy& copy); + + /// Initializing constructor + TEmulatedMapProxy(const char* cl_name); + + /// Standard destructor + virtual ~TEmulatedMapProxy(); + + /// Return the address of the value at index 'idx' + virtual void *At(UInt_t idx); + + /// Return the current size of the container + virtual UInt_t Size() const; + + /// Streamer for I/O handling + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &buff, void *pObj, int siz) { + TEmulatedCollectionProxy::Streamer(buff,pObj,siz); + } +}; + +#endif +#endif diff --git a/io/inc/TGenCollectionProxy.h b/io/inc/TGenCollectionProxy.h new file mode 100644 index 00000000000..595b0ad5282 --- /dev/null +++ b/io/inc/TGenCollectionProxy.h @@ -0,0 +1,311 @@ +// @(#)root/cont:$Name: $:$Id: TGenCollectionProxy.h,v 1.15 2004/10/13 15:30:22 rdm 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_TGenCollectionProxy +#define ROOT_TGenCollectionProxy +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionProxy +// +// Proxy around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TVirtualCollectionProxy.h" +#include "TCollectionProxy.h" +#include <typeinfo> +#include <string> + +class TGenCollectionProxy + : public TVirtualCollectionProxy, + public TCollectionProxy +{ + + /// Friend declaration + friend class TCollectionProxy; + +public: + + enum { + // Those 'bits' are used in conjunction with CINT's bit to store the 'type' + // info into one int + R__BIT_ISSTRING = 0x20000000, // We can optimized a value operation when the content are strings + R__BIT_ISTSTRING = 0x40000000, + kBOOL_t = 21 + }; + + + /** @class TGenCollectionProxy::Value TGenCollectionProxy.h TGenCollectionProxy.h + * + * Small helper to describe the Value_type or the key_type + * of an STL container. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ + struct Value { + ROOT::NewFunc_t fCtor; // Method cache for containee constructor + ROOT::DesFunc_t fDtor; // Method cache for containee destructor + ROOT::DelFunc_t fDelete; // Method cache for containee delete + unsigned int fCase; // type of data of Value_type + TClass* fType; // TClass of Value_type in collection + EDataType fKind; // kind of ROOT-fundamental type + size_t fSize; // fSize of the contained object + Value(const Value& inside); + Value(const std::string& info); + }; + + /**@class StreamHelper + * + * Helper class to facilitate I/O + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ + union StreamHelper { + bool boolean; + Char_t s_char; + Short_t s_short; + Int_t s_int; + Long_t s_long; + Long64_t s_longlong; + Float_t flt; + Double_t dbl; + UChar_t u_char; + UShort_t u_short; + UInt_t u_int; + ULong_t u_long; + ULong64_t u_longlong; + void* p_void; + void** pp_void; + char* kchar; + TString* tstr; + void* ptr() { + return *(&this->p_void); + } + std::string* str() { + return (std::string*)this; + } + const char* c_str() { + return ((std::string*)this)->c_str(); + } + const char* c_pstr() { + return (*(std::string**)this)->c_str(); + } + void set(void* p) { + *(&this->p_void) = p; + } + void read_std_string(TBuffer& b) { + TString s; + s.Streamer(b); + ((std::string*)this)->assign(s.Data()); + } + void* read_tstring(TBuffer& b) { + *((TString*)this) = ""; + ((TString*)this)->Streamer(b); + return this; + } + void read_std_string_pointer(TBuffer& b) { + TString s; + std::string* str = (std::string*) (ptr() ? ptr() : new std::string()); + s.Streamer(b); + *str = s; + set(str); + } + void write_std_string_pointer(TBuffer& b) { + const char* c = (const char*)(ptr() ? (*(std::string**)this)->c_str() : ""); + TString(c).Streamer(b); + } + void read_any_object(Value* v, TBuffer& b) { + void* p = ptr(); + if ( p ) { + if ( v->fDelete ) { // Compiled content: call Destructor + (*v->fDelete)(p); + } + else if ( v->fType ) { // Emulated content: call TClass::Delete + v->fType->Destructor(p); + } + else if ( v->fDtor ) { + (*v->fDtor)(p); + ::operator delete(p); + } + else { + ::operator delete(p); + } + } + set( b.ReadObjectAny(v->fType) ); + } + + void read_tstring_pointer(bool vsn3, TBuffer& b) { + TString* s = (TString*)ptr(); + if ( vsn3 ) { + if ( !s ) s = new TString(); + s->Replace(0, s->Length(), 0, 0); + s->Streamer(b); + set(s); + return; + } + if ( s ) delete s; + set( b.ReadObjectAny(TString::Class()) ); + } + void write_tstring_pointer(TBuffer& b) { + b.WriteObjectAny(ptr(), TString::Class()); + } + }; + + /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h + * + * Small helper to execute (compiler) generated function for the + * access to STL or other containers. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ + struct Method { + typedef void* (*Call_t)(void*); + Call_t call; + Method() : call(0) { } + Method(Call_t c) : call(c) { } + Method(const Method& m) : call(m.call) { } + void* invoke(void* obj) const { return (*call)(obj); } + }; + +protected: + typedef ROOT::Environ<char[64]> Env_t; + typedef std::vector<Env_t*> Proxies_t; + + std::string fName; // Name of the class being proxied. + bool fPointers; // Flag to indicate if containee has pointers (key or value) + Method fClear; // Method cache for container accessors: clear container + Method fSize; // Container accessors: size of container + Method fResize; // Container accessors: resize container + Method fFirst; // Container accessors: generic iteration: first + Method fNext; // Container accessors: generic iteration: next + Method fConstruct; // Container accessors: block construct + Method fDestruct; // Container accessors: block destruct + Method fFeed; // Container accessors: block feed + Method fCollect; // Method to collect objects from container + Value* fValue; // Descriptor of the container value type + Value* fVal; // Descriptor of the Value_type + Value* fKey; // Descriptor of the key_type + Env_t* fEnv; // Address of the currently proxied object + int fValOffset; // Offset from key to value (in maps) + int fValDiff; // Offset between two consecutive value_types (memory layout). + Proxies_t fProxyList; // Stack of recursive proxies + int fSTL_type; // STL container type + Info_t fTypeinfo; // Type information + + /// Late initialization of collection proxy + virtual TGenCollectionProxy* Initialize() const; + /// Some hack to avoid const-ness + virtual TGenCollectionProxy* InitializeEx(); + /// Call to delete/destruct individual contained item + virtual void DeleteItem(bool force, void* ptr) const; + /// Allow to check function pointers + void CheckFunctions() const; + +public: + + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TGenCollectionProxy(const TGenCollectionProxy& copy); + + /// Initializing constructor + TGenCollectionProxy(Info_t typ, size_t iter_size); + + /// Standard destructor + virtual ~TGenCollectionProxy(); + + /// Return a pointer to the TClass representing the container + virtual TClass *GetCollectionClass(); + + /// Return the sizeof the collection object. + virtual UInt_t Sizeof() const; + + /// Push new proxy environment + virtual void PushProxy(void *objstart); + + /// Pop old proxy environment + virtual void PopProxy(); + + /// Return true if the content is of type 'pointer to' + virtual Bool_t HasPointers() const; + + /// Return a pointer to the TClass representing the content. + virtual TClass *GetValueClass(); + + /// Set pointer to the TClass representing the content. + virtual void SetValueClass(TClass *newcl); + + /// If the content is a simple numerical value, return its type (see TDataType) + virtual EDataType GetType(); + + /// Return the address of the value at index 'idx' + virtual void *At(UInt_t idx); + + /// Clear the container + virtual void Clear(const char *opt = ""); + + /// Resize the container + virtual void Resize(UInt_t n, Bool_t force_delete); + + /// Return the current size of the container + virtual UInt_t Size() const; + + /// Block allocation of containees + virtual void* Allocate(UInt_t n, Bool_t forceDelete); + + /// Block commit of containees + virtual void Commit(void* env); + + /// Streamer function + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &refBuffer, void *pObject, int siz); + + /// TClassStreamer I/O overload + virtual void operator()(TBuffer &refBuffer, void *pObject); +}; + +template <typename T> +struct AnyCollectionProxy : public TGenCollectionProxy { + AnyCollectionProxy() + : TGenCollectionProxy(typeid(T::Cont_t),sizeof(T::Iter_t)) + { + fValDiff = sizeof(T::Value_t); + fValOffset = T::value_offset(); + fSize.call = T::size; + fResize.call = T::resize; + fNext.call = T::next; + fFirst.call = T::first; + fClear.call = T::clear; + fConstruct.call = T::construct; + fDestruct.call = T::destruct; + fFeed.call = T::feed; + CheckFunctions(); + } + virtual ~AnyCollectionProxy() { } +}; +#endif +#endif diff --git a/io/inc/TGenCollectionStreamer.h b/io/inc/TGenCollectionStreamer.h new file mode 100644 index 00000000000..862ffaca353 --- /dev/null +++ b/io/inc/TGenCollectionStreamer.h @@ -0,0 +1,89 @@ +// @(#)root/cont:$Name: $:$Id: TGenCollectionStreamer.h,v 1.15 2004/10/13 15:30:22 rdm 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_TGenCollectionStreamer +#define ROOT_TGenCollectionStreamer + +#ifndef __CINT__ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionStreamer +// +// Streamer around an arbitrary STL like container, which implements basic +// container functionality. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionProxy.h" + +class TGenCollectionStreamer : public TGenCollectionProxy { + +protected: + /// Stream I/O: Map input streamer + void ReadMap(int nElements, TBuffer &b); + /// Stream I/O: Object input streamer + void ReadObjects(int nElements, TBuffer &b); + /// Stream I/O: Primitive input streamer + void ReadPrimitives(int nElements, TBuffer &b); + /// Stream I/O: Map output streamer + void WriteMap(int nElements, TBuffer &b); + /// Stream I/O: Object output streamer + void WriteObjects(int nElements, TBuffer &b); + /// Stream I/O: Primitive output streamer + void WritePrimitives(int nElements, TBuffer &b); + +public: + /// Virtual copy constructor + virtual TVirtualCollectionProxy* Generate() const; + + /// Copy constructor + TGenCollectionStreamer(const TGenCollectionStreamer& copy); + + /// Initializing constructor + TGenCollectionStreamer(Info_t typ, size_t iter_size); + + /// Standard destructor + virtual ~TGenCollectionStreamer(); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &refBuffer); + + /// Streamer I/O overload + virtual void Streamer(TBuffer &buff, void *pObj, int siz) { + TGenCollectionProxy::Streamer(buff, pObj, siz); + } +}; + +template <typename T> +struct AnyCollectionStreamer : public TGenCollectionStreamer { + AnyCollectionStreamer() + : TGenCollectionStreamer(typeid(T::Cont_t),sizeof(T::Iter_t)) { + fValDiff = sizeof(T::Value_t); + fValOffset = T::value_offset(); + fSize.call = T::size; + fFirst.call = T::first; + fNext.call = T::next; + fClear.call = T::clear; + fResize.call = T::resize; + fCollect.call = T::collect; + fConstruct.call = T::construct; + fDestruct.call = T::destruct; + fFeed.call = T::feed; + CheckFunctions(); + } + virtual ~AnyCollectionStreamer() { } +}; + +// Forward declaration in the event of later seperation +typedef TGenCollectionStreamer TGenMapStreamer; + +#endif +#endif diff --git a/io/src/TEmulatedCollectionProxy.cxx b/io/src/TEmulatedCollectionProxy.cxx new file mode 100644 index 00000000000..834d5ca9762 --- /dev/null +++ b/io/src/TEmulatedCollectionProxy.cxx @@ -0,0 +1,437 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedCollectionProxy.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedCollectionProxy +// +// Streamer around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TEmulatedCollectionProxy.h" +#include "TStreamerInfo.h" +#include "TClassEdit.h" +#include "TError.h" +#include "TROOT.h" +#include <iostream> + +/// Build a Streamer for an emulated vector whose type is 'name'. +TEmulatedCollectionProxy::TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy) +: TGenCollectionProxy(copy) +{ +} + +/// Build a Streamer for a collection whose type is described by 'collectionClass'. +TEmulatedCollectionProxy::TEmulatedCollectionProxy(const char* cl_name) +: TGenCollectionProxy(typeid(std::vector<char>), sizeof(std::vector<char>::iterator)) +{ + fName = cl_name; + Initialize(); +} + +/// Standard destructor +TEmulatedCollectionProxy::~TEmulatedCollectionProxy() { +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TEmulatedCollectionProxy::Generate() const { + if ( !fClass ) Initialize(); + return new TEmulatedCollectionProxy(*this); +} + +/// Proxy initializer +TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx() { + fClass = gROOT->GetClass(fName.c_str()); + fEnv = 0; + fKey = 0; + if ( fClass ) { + int nested = 0; + std::vector<std::string> inside; + fPointers = false; + int num = TClassEdit::GetSplit(fName.c_str(),inside,nested); + if ( num > 1 ) { + std::string nam; + fSTL_type = TClassEdit::STLKind(inside[0].c_str()); + // std::cout << "Initialized " << typeid(*this).name() << ":" << fName << std::endl; + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + fKey = new Value(inside[1]); + fVal = new Value(inside[2]); + fPointers |= 0 != (fKey->fCase&G__BIT_ISPOINTER); + if ( 0 == fValDiff ) { + fValDiff = fKey->fSize + fVal->fSize; + } + if ( 0 == fValOffset ) { + fValOffset = fKey->fSize; + } + break; + default: + fVal = new Value(inside[1]); + if ( 0 == fValDiff ) { + fValDiff = fVal->fSize; + } + break; + } + fValue = new Value(*fVal); + fPointers |= 0 != (fVal->fCase&G__BIT_ISPOINTER); + return this; + } + Fatal("TEmulatedCollectionProxy","Components of %s not analysed!",fClass->GetName()); + } + Fatal("TEmulatedCollectionProxy","Collection class %s not found!",fTypeinfo.name()); + return 0; +} + +/// Return the current size of the container +UInt_t TEmulatedCollectionProxy::Size() const { + if ( fEnv && fEnv->object ) { + return fEnv->size = PCont_t(fEnv->object)->size()/fValDiff; + } + Fatal("TEmulatedCollectionProxy","Size> Logic error - no proxy object set."); + return 0; +} + +/// Clear the emulated collection. +void TEmulatedCollectionProxy::Clear(const char* opt) { + Resize(0, opt && *opt=='f'); +} + +/// Shrink the container +void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t /* force */ ) { + typedef std::string String_t; + PCont_t c = PCont_t(fEnv->object); + char* addr = ((char*)fEnv->start) + fValDiff*left; + size_t i; + + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + addr = ((char*)fEnv->start) + fValDiff*left; + switch(fKey->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i= fKey->fType ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) { + // Call emulation in case non-compiled content + fKey->fDtor ? (*fKey->fDtor)(addr) : fKey->fType->Destructor(addr, kTRUE); + } + break; + case R__BIT_ISSTRING: + for( i=left; i<nCurr; ++i, addr += fValDiff ) + ((std::string*)addr)->~String_t(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + for( i=left; i<nCurr; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + void* ptr = i->ptr(); + if ( fKey->fDelete ) { // Case of compiled content + (*fKey->fDelete)(ptr); + } + else if ( fKey->fType ) { // Case of emulated content + fKey->fType->Destructor(ptr); + } + else if ( fKey->fDtor ) { // Case of compiled content + (*fKey->fDtor)(ptr); + ::operator delete(ptr); + } + else { + ::operator delete(i->ptr()); + } + i->set(0); + } + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete (std::string*)i; + i->set(0); + } + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete i->tstr; + i->set(0); + } + break; + } + addr = ((char*)fEnv->start)+fKey->fSize+fValDiff*left; + // DO NOT break; just continue + + // General case for all values + default: + switch( fVal->fCase ) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i=fVal->fDtor ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) { + // Call emulation in case non-compiled content + fKey->fDtor ? (*fKey->fDtor)(addr) : fKey->fType->Destructor(addr,kTRUE); + } + break; + case R__BIT_ISSTRING: + for( i=left; i<nCurr; ++i, addr += fValDiff ) + ((std::string*)addr)->~String_t(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + for( i=left; i<nCurr; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + void* p = i->ptr(); + if ( p ) { + if ( fVal->fDelete ) { // Case of compiled content + (*fVal->fDelete)(p); + } + else if ( fVal->fType ) { // Case of emultated content + fVal->fType->Destructor(p); + } + else if ( fVal->fDtor ) { // Case of compiled content + (*fVal->fDtor)(p); + ::operator delete(p); + } + else { + ::operator delete(p); + } + } + i->set(0); + } + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete (std::string*)i; + i->set(0); + } + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) { + StreamHelper* i = *(StreamHelper**)addr; + delete i->tstr; + i->set(0); + } + break; + } + } + c->resize(left*fValDiff,0); + fEnv->start = left>0 ? &(*c->begin()) : 0; + return; +} + +/// Expand the container +void TEmulatedCollectionProxy::Expand(UInt_t nCurr, UInt_t left) { + size_t i; + PCont_t c = PCont_t(fEnv->object); + c->resize(left*fValDiff,0); + fEnv->start = left>0 ? &(*c->begin()) : 0; + char* addr = ((char*)fEnv->start) + fValDiff*nCurr; + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + switch(fKey->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i=fVal->fCtor ? nCurr : left; i<left; ++i, addr += fValDiff ) + (*fKey->fCtor)(addr); + break; + case R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + ::new(addr) std::string(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + *(void**)addr = 0; + break; + } + addr = ((char*)fEnv->start)+fKey->fSize+fValDiff*nCurr; + // DO NOT break; just continue + + // General case for all values + default: + switch(fVal->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + break; + case G__BIT_ISCLASS: + for( i=fVal->fCtor ? nCurr : left; i<left; ++i, addr += fValDiff ) + (*fVal->fCtor)(addr); + break; + case R__BIT_ISSTRING: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + ::new(addr) std::string(); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + case G__BIT_ISPOINTER|R__BIT_ISSTRING: + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + for( i=nCurr; i<left; ++i, addr += fValDiff ) + *(void**)addr = 0; + break; + } + break; + } +} +/// Resize the container +void TEmulatedCollectionProxy::Resize(UInt_t left, Bool_t force) { + if ( fEnv && fEnv->object ) { + size_t nCurr = Size(); + PCont_t c = PCont_t(fEnv->object); + fEnv->start = left>0 ? &(*c->begin()) : 0; + if ( left == nCurr ) { + return; + } + else if ( left < nCurr ) { + Shrink(nCurr, left, force); + return; + } + Expand(nCurr, left); + return; + } + Fatal("TEmulatedCollectionProxy","Resize> Logic error - no proxy object set."); +} + +/// Return the address of the value at index 'idx' +void* TEmulatedCollectionProxy::At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + PCont_t c = PCont_t(fEnv->object); + return idx<(c->size()/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0; + } + Fatal("TEmulatedCollectionProxy","At> Logic error - no proxy object set."); + return 0; +} + +void* TEmulatedCollectionProxy::Allocate(UInt_t n, Bool_t forceDelete) { + Resize(n, forceDelete); + return fEnv; +} + +void TEmulatedCollectionProxy::Commit(void* /* env */ ) { +} + +/// Object input streamer +void TEmulatedCollectionProxy::ReadItems(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + StreamHelper* itm = (StreamHelper*)At(0); + switch (fVal->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(fVal->fKind) ) { + case kChar_t: b.ReadFastArray(&itm->s_char , nElements); break; + case kShort_t: b.ReadFastArray(&itm->s_short , nElements); break; + case kInt_t: b.ReadFastArray(&itm->s_int , nElements); break; + case kLong_t: b.ReadFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.ReadFastArray(&itm->flt , nElements); break; + case kDouble_t: b.ReadFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.ReadFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.ReadFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.ReadFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.ReadFastArray(&itm->u_int , nElements); break; + case kULong_t: b.ReadFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind); + } + break; +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fVal->fType) ); + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->read_any_object(fVal,b) ); + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ); +#endif + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ); + } +#undef DOLOOP +} + +/// Object output streamer +void TEmulatedCollectionProxy::WriteItems(int nElements, TBuffer &b) { + StreamHelper* itm = (StreamHelper*)At(0); + switch (fVal->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + itm = (StreamHelper*)At(0); + switch( int(fVal->fKind) ) { + case kChar_t: b.WriteFastArray(&itm->s_char , nElements); break; + case kShort_t: b.WriteFastArray(&itm->s_short , nElements); break; + case kInt_t: b.WriteFastArray(&itm->s_int , nElements); break; + case kLong_t: b.WriteFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.WriteFastArray(&itm->flt , nElements); break; + case kDouble_t: b.WriteFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.WriteFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.WriteFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.WriteFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.WriteFastArray(&itm->u_int , nElements); break; + case kULong_t: b.WriteFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind); + } + break; +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fVal->fType) ); + case R__BIT_ISSTRING: + DOLOOP( TString(i->c_str()).Streamer(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) ); + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + DOLOOP( i->write_std_string_pointer(b) ); +#endif + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + DOLOOP( i->write_tstring_pointer(b) ); + } +#undef DOLOOP +} + +/// TClassStreamer IO overload +void TEmulatedCollectionProxy::Streamer(TBuffer &b) { + if ( b.IsReading() ) { //Read mode + int nElements = 0; + b >> nElements; + if ( fEnv->object ) { + Resize(nElements,true); + } + if ( nElements > 0 ) { + ReadItems(nElements, b); + } + } + else { // Write case + int nElements = fEnv->object ? *(size_t*)fSize.invoke(fEnv) : 0; + b << nElements; + if ( nElements > 0 ) { + WriteItems(nElements, b); + } + } +} diff --git a/io/src/TEmulatedMapProxy.cxx b/io/src/TEmulatedMapProxy.cxx new file mode 100644 index 00000000000..e591582e010 --- /dev/null +++ b/io/src/TEmulatedMapProxy.cxx @@ -0,0 +1,221 @@ +// @(#)root/cont:$Name: $:$Id: TEmulatedMapProxy.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TEmulatedMapProxy +// +// Streamer around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TEmulatedMapProxy.h" +#include "TStreamerInfo.h" +#include "TClassEdit.h" +#include "TError.h" + +/// Build a Streamer for an emulated vector whose type is 'name'. +TEmulatedMapProxy::TEmulatedMapProxy(const TEmulatedMapProxy& copy) +: TEmulatedCollectionProxy(copy) +{ + if ( !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap) ) { + Fatal("TEmulatedMapProxy","Class %s is not a map-type!",fName.c_str()); + } +} + +/// Build a Streamer for a collection whose type is described by 'collectionClass'. +TEmulatedMapProxy::TEmulatedMapProxy(const char* cl_name) +: TEmulatedCollectionProxy(cl_name) +{ + fName = cl_name; + Initialize(); + if ( !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap) ) { + Fatal("TEmulatedMapProxy","Class %s is not a map-type!",fName.c_str()); + } +} + +/// Standard destructor +TEmulatedMapProxy::~TEmulatedMapProxy() { +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TEmulatedMapProxy::Generate() const { + if ( !fClass ) Initialize(); + return new TEmulatedMapProxy(*this); +} + +/// Return the address of the value at index 'idx' +void* TEmulatedMapProxy::At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + PCont_t c = PCont_t(fEnv->object); + return idx<(c->size()/fValDiff) ? ((char*)&(*c->begin())) + idx*fValDiff : 0; + } + Fatal("TEmulatedMapProxy","At> Logic error - no proxy object set."); + return 0; +} + +/// Return the current size of the container +UInt_t TEmulatedMapProxy::Size() const { + if ( fEnv && fEnv->object ) { + PCont_t c = PCont_t(fEnv->object); + return fEnv->size = (c->size()/fValDiff); + } + Fatal("TEmulatedMapProxy","Size> Logic error - no proxy object set."); + return 0; +} + +/// Map input streamer +void TEmulatedMapProxy::ReadMap(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + int idx, loop, off[2] = {0, fKey->fSize }; + Value *v, *val[2] = { fKey, fVal }; + StreamHelper* helper; + float f; + char* addr = 0; + char* temp = (char*)At(0); + for ( idx = 0; idx < nElements; ++idx ) { + addr = temp + idx*fValDiff; + for ( loop=0; loop<2; loop++) { + addr += off[loop]; + helper = (StreamHelper*)addr; + v = val[loop]; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b >> helper->s_char; break; + case kShort_t: b >> helper->s_short; break; + case kInt_t: b >> helper->s_int; break; + case kLong_t: b >> helper->s_long; break; + case kLong64_t: b >> helper->s_longlong; break; + case kFloat_t: b >> helper->flt; break; + case kDouble_t: b >> helper->dbl; break; + case kBOOL_t: b >> helper->boolean; break; + case kUChar_t: b >> helper->u_char; break; + case kUShort_t: b >> helper->u_short; break; + case kUInt_t: b >> helper->u_int; break; + case kULong_t: b >> helper->u_long; break; + case kULong64_t: b >> helper->u_longlong; break; + case kDouble32_t:b >> f; + helper->dbl = double(f); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedMapProxy","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(helper,v->fType); + break; + case R__BIT_ISSTRING: + helper->read_std_string(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + helper->set(b.ReadObjectAny(v->fType)); + break; + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + helper->read_std_string_pointer(b); +#endif + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + helper->read_tstring_pointer(vsn3,b); + break; + } + } + } +} + +/// Map output streamer +void TEmulatedMapProxy::WriteMap(int nElements, TBuffer &b) { + Value *v, *val[2] = { fKey, fVal }; + int off[2] = { 0, fKey->fSize }; + StreamHelper* i; + char* addr = 0; + char* temp = (char*)At(0); + for (int loop, idx = 0; idx < nElements; ++idx ) { + addr = temp + idx*fValDiff; + for ( loop = 0; loop<2; ++loop ) { + addr += off[loop]; + i = (StreamHelper*)addr; + v = val[loop]; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b << i->s_char; break; + case kShort_t: b << i->s_short; break; + case kInt_t: b << i->s_int; break; + case kLong_t: b << i->s_long; break; + case kLong64_t: b << i->s_longlong; break; + case kFloat_t: b << i->flt; break; + case kDouble_t: b << i->dbl; break; + case kBOOL_t: b << i->boolean; break; + case kUChar_t: b << i->u_char; break; + case kUShort_t: b << i->u_short; break; + case kUInt_t: b << i->u_int; break; + case kULong_t: b << i->u_long; break; + case kULong64_t: b << i->u_longlong; break; + case kDouble32_t:b << float(i->dbl); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TEmulatedMapProxy","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(i,v->fType); + break; + case R__BIT_ISSTRING: + TString(i->c_str()).Streamer(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + b.WriteObjectAny(i->ptr(),v->fType); + break; + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + i->write_std_string_pointer(b); +#endif + break; + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + i->write_tstring_pointer(b); + break; + } + } + } +} + +/// TClassStreamer IO overload +void TEmulatedMapProxy::Streamer(TBuffer &b) { + if ( b.IsReading() ) { //Read mode + int nElements = 0; + b >> nElements; + if ( fEnv->object ) { + Resize(nElements,true); + } + if ( nElements > 0 ) { + ReadMap(nElements, b); + } + } + else { // Write case + int nElements = fEnv->object ? Size() : 0; + b << nElements; + if ( nElements > 0 ) { + WriteMap(nElements, b); + } + } +} diff --git a/io/src/TGenCollectionProxy.cxx b/io/src/TGenCollectionProxy.cxx new file mode 100644 index 00000000000..97e3dfa76b9 --- /dev/null +++ b/io/src/TGenCollectionProxy.cxx @@ -0,0 +1,714 @@ +// @(#)root/cont:$Name: $:$Id: TGenVectorProxy.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionProxy +// +// Proxy around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionProxy.h" +#include "TStreamerElement.h" +#include "TClassEdit.h" +#include "Property.h" +#include "TClass.h" +#include "TError.h" +#include "TROOT.h" +#include "Api.h" +#include <iostream> + +#define MESSAGE(which,text) + +/** @class TGenVectorProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenVectorProxy : public TGenCollectionProxy { +public: + /// Standard Destructor + TGenVectorProxy(const TGenCollectionProxy& c) : TGenCollectionProxy(c) { + } + /// Standard Destructor + virtual ~TGenVectorProxy() { + } + /// Return the address of the value at index 'idx' + virtual void* At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + fEnv->idx = idx; + switch( idx ) { + case 0: + return fEnv->start = fFirst.invoke(fEnv); + default: + return ((char*)fEnv->start) + fValDiff*idx; + } + } + Fatal("TGenVectorProxy","At> Logic error - no proxy object set."); + return 0; + } + /// Call to delete/destruct individual item + virtual void DeleteItem(bool force, void* ptr) const { + if ( force && ptr ) { + if ( fValue->fDelete ) { + (*fValue->fDelete)(ptr); + } + else if ( fVal->fType ) { + fVal->fType->Destructor(ptr); + } + else { + ::operator delete(ptr); + } + } + } +}; + +/** @class TGenListProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenListProxy : public TGenVectorProxy { +public: + /// Standard Destructor + TGenListProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c) { + } + /// Standard Destructor + virtual ~TGenListProxy() { + } + /// Return the address of the value at index 'idx' + void* At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + switch( idx ) { + case 0: + fEnv->idx = idx; + return fEnv->start = fFirst.invoke(fEnv); + default: { + fEnv->idx = idx - fEnv->idx; + void* result = fNext.invoke(fEnv); + fEnv->idx = idx; + return result; + } + } + } + Fatal("TGenListProxy","At> Logic error - no proxy object set."); + return 0; + } +}; + +/** @class TGenSetProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenSetProxy : public TGenVectorProxy { +public: + /// Standard Destructor + TGenSetProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c) { + } + /// Standard Destructor + virtual ~TGenSetProxy() { + } + /// Return the address of the value at index 'idx' + void* At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + if ( fEnv->temp ) { + return (((char*)fEnv->temp)+idx*fValDiff); + } + switch( idx ) { + case 0: + fEnv->idx = idx; + return fEnv->start = fFirst.invoke(fEnv); + default: { + fEnv->idx = idx - fEnv->idx; + void* result = fNext.invoke(fEnv); + fEnv->idx = idx; + return result; + } + } + } + Fatal("TGenSetProxy","At> Logic error - no proxy object set."); + return 0; + } +}; + +/** @class TGenMapProxy TGenCollectionProxy.cxx cont/TGenCollectionProxy.cxx + * + * Localoptimization class. + * + * Collection proxies get copied. On copy we switch the type of the + * proxy to the concrete STL type. The concrete types are optimized + * for element access. + * + * @author M.Frank + * @version 1.0 + * @date 10/10/2004 + */ +class TGenMapProxy : public TGenSetProxy { +public: + /// Standard Destructor + TGenMapProxy(const TGenCollectionProxy& c) : TGenSetProxy(c) { + } + /// Standard Destructor + virtual ~TGenMapProxy() { + } + /// Call to delete/destruct individual item + virtual void DeleteItem(bool /* force */, void* ptr) const { + if ( fKey->fCase&G__BIT_ISPOINTER ) { + if ( *(void**)ptr ) { + (*fKey->fDelete)(*(void**)ptr); + } + } + if ( fVal->fCase&G__BIT_ISPOINTER ) { + char *addr = ((char*)ptr)+fKey->fSize; + if ( *(void**)addr ) (*fVal->fDelete)(*(void**)addr); + } + } +}; + +TGenCollectionProxy::Value::Value(const Value& copy) { + fType = copy.fType; + fCase = copy.fCase; + fKind = copy.fKind; + fSize = copy.fSize; + fCtor = copy.fCtor; + fDtor = copy.fDtor; + fDelete = copy.fDelete; +} + +TGenCollectionProxy::Value::Value(const std::string& inside) { + fType = 0; + fCase = 0; + fCtor = 0; + fDtor = 0; + fDelete = 0; + fSize = std::string::npos; + fKind = kNoType_t; + std::string intype = TClassEdit::ShortType(inside.c_str(),TClassEdit::kDropTrailStar ); + if ( inside.substr(0,6) == "string" || inside.substr(0,11) == "std::string" ) { + fCase = R__BIT_ISSTRING; + fType = gROOT->GetClass("string"); + fCtor = fType->GetNew(); + fDtor = fType->GetDestructor(); + fDelete = fType->GetDelete(); + switch(inside[inside.length()-1]) { + case '*': + fCase |= G__BIT_ISPOINTER; + fSize = sizeof(void*); + break; + default: + fSize = sizeof(std::string); + break; + } + } + else { + G__TypeInfo ti(inside.c_str()); + if ( !ti.IsValid() ) { + if (intype != inside) { + fCase |= G__BIT_ISPOINTER; + fSize = sizeof(void*); + } + fType = gROOT->GetClass(intype.c_str()); + if (fType) { + fCase |= G__BIT_ISCLASS; + fCtor = fType->GetNew(); + fDtor = fType->GetDestructor(); + fDelete = fType->GetDelete(); + } + else { + // either we have an Emulated enum or a really unknown class! + // let's just claim its an enum :( + fCase = G__BIT_ISENUM; + fSize = sizeof(Int_t); + fKind = kInt_t; + } + } + else { + long P = ti.Property(); + if ( P&G__BIT_ISPOINTER ) { + fSize = sizeof(void*); + } + if ( P&G__BIT_ISSTRUCT ) { + P |= G__BIT_ISCLASS; + } + if ( P&G__BIT_ISCLASS ) { + fType = gROOT->GetClass(intype.c_str()); + Assert(fType); + fCtor = fType->GetNew(); + fDtor = fType->GetDestructor(); + fDelete = fType->GetDelete(); + } + else if ( P&G__BIT_ISFUNDAMENTAL ) { + TDataType *fundType = gROOT->GetType( intype.c_str() ); + fKind = (EDataType)fundType->GetType(); + fSize = ti.Size(); + Assert(fKind>0 && fKind<20); + } + else if ( P&G__BIT_ISENUM ) { + fSize = sizeof(int); + fKind = kInt_t; + } + fCase = P & (G__BIT_ISPOINTER|G__BIT_ISFUNDAMENTAL|G__BIT_ISENUM|G__BIT_ISCLASS); + if (fType == TString::Class() && (fCase&G__BIT_ISPOINTER)) { + fCase |= R__BIT_ISTSTRING; + } + } + } + if ( fSize == std::string::npos ) { + if ( fType == 0 ) { + Fatal("TGenCollectionProxy","Could not find %s!",inside.c_str()); + } + fSize = fType->Size(); + } +} + +/// Build a proxy for an emulated container. +TGenCollectionProxy::TGenCollectionProxy(const TGenCollectionProxy& copy) +: TVirtualCollectionProxy(copy.fClass), + fTypeinfo(copy.fTypeinfo) +{ + fEnv = 0; + fName = copy.fName; + fPointers = copy.fPointers; + fSTL_type = copy.fSTL_type; + fSize.call = copy.fSize.call; + fNext.call = copy.fNext.call; + fFirst.call = copy.fFirst.call; + fClear.call = copy.fClear.call; + fResize.call = copy.fResize.call; + fDestruct.call = copy.fDestruct.call; + fConstruct.call = copy.fConstruct.call; + fFeed.call = copy.fFeed.call; + fCollect.call = copy.fCollect.call; + fValOffset = copy.fValOffset; + fValDiff = copy.fValDiff; + fValue = copy.fValue ? new Value(*copy.fValue) : 0; + fVal = copy.fVal ? new Value(*copy.fVal) : 0; + fKey = copy.fKey ? new Value(*copy.fKey) : 0; +} + +/// Build a proxy for a collection whose type is described by 'collectionClass'. +TGenCollectionProxy::TGenCollectionProxy(Info_t info, size_t iter_size) +: TVirtualCollectionProxy(0), + fTypeinfo(info) +{ + fEnv = 0; + fSize.call = 0; + fFirst.call = 0; + fNext.call = 0; + fClear.call = 0; + fResize.call = 0; + fDestruct.call = 0; + fConstruct.call = 0; + fCollect.call = 0; + fFeed.call = 0; + fValue = 0; + fKey = 0; + fVal = 0; + fValOffset = 0; + fValDiff = 0; + fPointers = false; + Env_t e; + if ( iter_size > sizeof(e.buff) ) { + Fatal("TGenCollectionProxy", + "%s %s are too large:%d bytes. Maximum is:%d bytes", + "Iterators for collection", + fClass->GetName(), + iter_size, + sizeof(e.buff)); + } +} + +/// Standard destructor +TGenCollectionProxy::~TGenCollectionProxy() { + for(Proxies_t::iterator i=fProxyList.begin(); i != fProxyList.end(); ++i) { + if ( (*i) ) delete (*i); + } + fProxyList.clear(); + if ( fValue ) delete fValue; + if ( fVal ) delete fVal; + if ( fKey ) delete fKey; +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TGenCollectionProxy::Generate() const { + if ( !fClass ) Initialize(); + switch(fSTL_type) { + case TClassEdit::kVector: + return new TGenVectorProxy(*this); + case TClassEdit::kList: + return new TGenListProxy(*this); + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + return new TGenMapProxy(*this); + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + return new TGenSetProxy(*this); + default: + return new TGenCollectionProxy(*this); + } +} + +/// Proxy initializer +TGenCollectionProxy *TGenCollectionProxy::Initialize() const { + TGenCollectionProxy* p = const_cast<TGenCollectionProxy*>(this); + if ( fClass ) return p; + return p->InitializeEx(); +} + +/// Check existence of function pointers +void TGenCollectionProxy::CheckFunctions() const { + if ( 0 == fSize.call ) { + Fatal("TGenCollectionProxy","No 'size' function pointer for class %s present.",fName.c_str()); + } + if ( 0 == fResize.call ) { + Fatal("TGenCollectionProxy","No 'resize' function for class %s present.",fName.c_str()); + } + if ( 0 == fNext.call ) { + Fatal("TGenCollectionProxy","No 'next' function for class %s present.",fName.c_str()); + } + if ( 0 == fFirst.call ) { + Fatal("TGenCollectionProxy","No 'begin' function for class %s present.",fName.c_str()); + } + if ( 0 == fClear.call ) { + Fatal("TGenCollectionProxy","No 'clear' function for class %s present.",fName.c_str()); + } + if ( 0 == fConstruct.call ) { + Fatal("TGenCollectionProxy","No 'block constructor' function for class %s present.",fName.c_str()); + } + if ( 0 == fDestruct.call ) { + Fatal("TGenCollectionProxy","No 'block destructor' function for class %s present.",fName.c_str()); + } + if ( 0 == fFeed.call ) { + Fatal("TGenCollectionProxy","No 'data feed' function for class %s present.",fName.c_str()); + } + if ( 0 == fCollect.call ) { + Fatal("TGenCollectionProxy","No 'data collect' function for class %s present.",fName.c_str()); + } +} + +/// Proxy initializer +TGenCollectionProxy *TGenCollectionProxy::InitializeEx() { + fClass = gROOT->GetClass(fTypeinfo); + if ( fClass ) { + fEnv = 0; + fName = fClass->GetName(); + fPointers = false; + int nested = 0; + std::vector<std::string> inside; + int num = TClassEdit::GetSplit(fClass->GetName(),inside,nested); + if ( num > 1 ) { + std::string nam; + fSTL_type = TClassEdit::STLKind(inside[0].c_str()); + switch ( fSTL_type ) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + nam = "pair<"+inside[1]+","+inside[2]; + nam += (nam[nam.length()-1]=='>') ? " >" : ">"; + fValue = new Value(nam); + fVal = new Value(inside[2]); + fKey = new Value(inside[1]); + fPointers = fPointers || (0 != (fKey->fCase&G__BIT_ISPOINTER)); + if ( 0 == fValDiff ) { + fValDiff = fKey->fSize + fVal->fSize; + } + if ( 0 == fValOffset ) { + fValOffset = fKey->fSize; + } + break; + default: + fValue = new Value(inside[1]); + fVal = new Value(*fValue); + if ( 0 == fValDiff ) { + fValDiff = fVal->fSize; + } + break; + } + fPointers = fPointers || (0 != (fVal->fCase&G__BIT_ISPOINTER)); + return this; + } + Fatal("TGenCollectionProxy","Components of %s not analysed!",fClass->GetName()); + } + Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name()); + return 0; +} + +/// Return a pointer to the TClass representing the container +TClass *TGenCollectionProxy::GetCollectionClass() { + return fClass ? fClass : Initialize()->fClass; +} + +/// Return the sizeof the collection object. +UInt_t TGenCollectionProxy::Sizeof() const { + return fClass->Size(); +} + +/// Return true if the content is of type 'pointer to' +Bool_t TGenCollectionProxy::HasPointers() const { + return fPointers; +} + +/// Return a pointer to the TClass representing the content. +TClass *TGenCollectionProxy::GetValueClass() { + return fValue->fType; +} + +/// Set pointer to the TClass representing the content. +void TGenCollectionProxy::SetValueClass(TClass *new_Value_type) { + fValue->fType = new_Value_type; +} + +/// If the content is a simple numerical value, return its type (see TDataType) +EDataType TGenCollectionProxy::GetType() { + return fValue->fKind; +} + +/// Return the address of the value at index 'idx' +void* TGenCollectionProxy::At(UInt_t idx) { + if ( fEnv && fEnv->object ) { + switch (fSTL_type) { + case TClassEdit::kVector: + fEnv->idx = idx; + switch( idx ) { + case 0: + return fEnv->start = fFirst.invoke(fEnv); + default: + return ((char*)fEnv->start) + fValDiff*idx; + } + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + if ( fEnv->temp ) { + return (((char*)fEnv->temp)+idx*fValDiff); + } + default: + switch( idx ) { + case 0: + fEnv->idx = idx; + return fEnv->start = fFirst.invoke(fEnv); + default: { + fEnv->idx = idx - fEnv->idx; + void* result = fNext.invoke(fEnv); + fEnv->idx = idx; + return result; + } + } + } + } + Fatal("TGenCollectionProxy","At> Logic error - no proxy object set."); + return 0; +} + +/// Clear the emulated collection. +void TGenCollectionProxy::Clear(const char* opt) { + if ( fEnv && fEnv->object ) { + if ( fPointers && opt && *opt=='f' ) { + size_t i, n = *(size_t*)fSize.invoke(fEnv); + if ( n > 0 ) { + for (i=0; i<n; ++i) + DeleteItem(true, TGenCollectionProxy::At(i)); + } + } + fClear.invoke(fEnv); + } +} + +/// Return the current size of the container +UInt_t TGenCollectionProxy::Size() const { + if ( fEnv && fEnv->object ) { + return *(size_t*)fSize.invoke(fEnv); + } + Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set."); + return 0; +} + +/// Resize the container +void TGenCollectionProxy::Resize(UInt_t n, Bool_t force) { + if ( fEnv && fEnv->object ) { + if ( force && fPointers ) { + size_t i, nold = *(size_t*)fSize.invoke(fEnv); + if ( n != nold ) { + for (i=n; i<nold; ++i) + DeleteItem(true, *(void**)TGenCollectionProxy::At(i)); + } + } + MESSAGE(3, "Resize(n)" ); + fEnv->size = n; + fResize.invoke(fEnv); + return; + } + Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set."); +} + +void* TGenCollectionProxy::Allocate(UInt_t n, Bool_t /* forceDelete */ ) { + if ( fEnv && fEnv->object ) { + switch ( fSTL_type ) { + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + if ( fPointers ) + Clear("force"); + else + fClear.invoke(fEnv); + ++fEnv->refCount; + fEnv->size = n; + fEnv->start = fEnv->temp = ::operator new(fValDiff*n); + fConstruct.invoke(fEnv); + return fEnv; + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + if( fPointers ) { + Clear("force"); + } + fEnv->size = n; + fResize.invoke(fEnv); + return fEnv; + } + } + return 0; +} + +void TGenCollectionProxy::Commit(void* env) { + switch (fSTL_type) { + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + return; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + if ( env ) { + Env_t* e = (Env_t*)env; + if ( e->object ) { + e->start = e->temp; + fFeed.invoke(e); + } + fDestruct.invoke(e); + e->start = 0; + --e->refCount; + } + return; + default: + return; + } +} + +void TGenCollectionProxy::PushProxy(void *objstart) { + if ( !fClass ) Initialize(); + if ( !fProxyList.empty() ) { + Env_t* back = fProxyList.back(); + if ( back->object == objstart ) { + back->refCount++; + fProxyList.push_back(back); + fEnv = back; + return; + } + } + Env_t* e = new Env_t(); + e->size = 0; + e->refCount = 1; + e->object = objstart; + e->temp = e->start = 0; + ::memset(e->buff,0,sizeof(e->buff)); + fProxyList.push_back(e); + fEnv = e; +} + +void TGenCollectionProxy::PopProxy() { + if ( !fProxyList.empty() ) { + Env_t* e = fProxyList.back(); + if ( --e->refCount <= 0 ) { + if ( e->temp ) + ::operator delete(e->temp); + delete e; + } + fProxyList.pop_back(); + } + fEnv = 0; +} + +/// Call to delete/destruct individual item +void TGenCollectionProxy::DeleteItem(bool force, void* ptr) const { + // This needs correction in the LCG dict... + // Pointers are not initialized to NULL! + if ( force && ptr ) { + switch (fSTL_type) { + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + if ( fKey->fCase&G__BIT_ISPOINTER ) { + if (*(void**)ptr) (*fKey->fDelete)(*(void**)ptr); + } + if ( fVal->fCase&G__BIT_ISPOINTER ) { + char *addr = ((char*)ptr)+fKey->fSize; + if (*(void**)addr) (*fVal->fDelete)(*(void**)addr); + } + // (*fValue->fDtor)(ptr); No: pair must stay intact ! + break; + default: + if ( fVal->fCase&G__BIT_ISPOINTER ) { + (*fVal->fDelete)(*(void**)ptr); + } + break; + } + } +} + +void TGenCollectionProxy::Streamer(TBuffer &buff) { + if ( fEnv ) { + GetCollectionClass()->Streamer( fEnv->object, buff ); + return; + } + Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set."); +} + +/// Streamer I/O overload +void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ ) { + TPushPop env(this, objp); + Streamer(buff); +} + +/// TClassStreamer IO overload +void TGenCollectionProxy::operator()(TBuffer &b, void *objp) { + Streamer(b, objp, 0); +} + diff --git a/io/src/TGenCollectionStreamer.cxx b/io/src/TGenCollectionStreamer.cxx new file mode 100644 index 00000000000..e94b36a4fbe --- /dev/null +++ b/io/src/TGenCollectionStreamer.cxx @@ -0,0 +1,490 @@ +// @(#)root/cont:$Name: $:$Id: TGenCollectionStreamer.cxx,v 1.26 2004/10/13 15:30:22 rdm Exp $ +// Author: Markus Frank 28/10/04 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TGenCollectionStreamer +// +// Streamer around an arbitrary container, which implements basic +// functionality and iteration. +// +// 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. +// +////////////////////////////////////////////////////////////////////////// + +#include "TGenCollectionStreamer.h" +#include "TStreamerInfo.h" +#include "TClassEdit.h" +#include "TError.h" +#include "TROOT.h" +#include <iostream> + +/// Build a Streamer for an emulated vector whose type is 'name'. +TGenCollectionStreamer::TGenCollectionStreamer(const TGenCollectionStreamer& copy) +: TGenCollectionProxy(copy) +{ +} + +/// Build a Streamer for a collection whose type is described by 'collectionClass'. +TGenCollectionStreamer::TGenCollectionStreamer(Info_t info, size_t iter_size) +: TGenCollectionProxy(info, iter_size) +{ +} + +/// Standard destructor +TGenCollectionStreamer::~TGenCollectionStreamer() { +} + +/// Virtual copy constructor +TVirtualCollectionProxy* TGenCollectionStreamer::Generate() const { + if ( !fClass ) Initialize(); + return new TGenCollectionStreamer(*this); +} + +/// Primitive input streamer +void TGenCollectionStreamer::ReadPrimitives(int nElements, TBuffer &b) { + size_t len = fValDiff*nElements; + char buffer[8096]; + bool feed = false; + void* memory = 0; + StreamHelper* itm = 0; + fEnv->size = nElements; + switch ( fSTL_type ) { + case TClassEdit::kVector: + if ( fVal->fKind != EDataType(kBOOL_t) ) { + itm = (StreamHelper*)fResize.invoke(fEnv); + break; + } + default: + feed = true; + itm = (StreamHelper*)(len<sizeof(buffer) ? buffer : memory=::operator new(len)); + break; + } + fEnv->start = itm; + switch( int(fValue->fKind) ) { + case kChar_t: b.ReadFastArray(&itm->s_char , nElements); break; + case kShort_t: b.ReadFastArray(&itm->s_short , nElements); break; + case kInt_t: b.ReadFastArray(&itm->s_int , nElements); break; + case kLong_t: b.ReadFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.ReadFastArray(&itm->flt , nElements); break; + case kDouble_t: b.ReadFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.ReadFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.ReadFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.ReadFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.ReadFastArray(&itm->u_int , nElements); break; + case kULong_t: b.ReadFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",fValue->fKind); + } + if ( feed ) { // need to feed in data... + fEnv->start = fFeed.invoke(fEnv); + if ( memory ) { + ::operator delete(memory); + } + } +} + +/// Object input streamer +void TGenCollectionStreamer::ReadObjects(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + size_t len = fValDiff*nElements; + StreamHelper* itm = 0; + char buffer[8096]; + void* memory = 0; + + fEnv->size = nElements; + switch ( fSTL_type ) { + // Simple case: contiguous memory. get address of first, then jump. + case TClassEdit::kVector: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + itm = (StreamHelper*)fResize.invoke(fEnv); + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType) ); + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->set(b.ReadObjectAny(fValue->fType)) ); + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ); +#endif + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ); + } +#undef DOLOOP + break; + + // No contiguous memory, but resize is possible + // Hence accessing objects using At(i) should be not too much an overhead + case TClassEdit::kList: + case TClassEdit::kDeque: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)TGenCollectionProxy::At(idx); { x ;} ++idx;} break;} + fResize.invoke(fEnv); + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType) ); + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->set( b.ReadObjectAny(fValue->fType) ) ); + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ); +#endif + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ); + } +#undef DOLOOP + break; + + // Rather troublesome case: Objects can only be fed into the container + // Once they are created. Need to take memory from stack or heap. + case TClassEdit::kMultiSet: + case TClassEdit::kSet: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;}} + fEnv->start = itm = (StreamHelper*)(len<sizeof(buffer) ? buffer : memory=::operator new(len)); + fConstruct.invoke(fEnv); + switch ( fValue->fCase ) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType) ) + fFeed.invoke(fEnv); + fDestruct.invoke(fEnv); + break; + case R__BIT_ISSTRING: + DOLOOP( i->read_std_string(b) ) + fFeed.invoke(fEnv); + fDestruct.invoke(fEnv); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( i->set(b.ReadObjectAny(fValue->fType)) ); + fFeed.invoke(fEnv); + break; + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + DOLOOP( i->read_std_string_pointer(b) ) + fFeed.invoke(fEnv); +#endif + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + DOLOOP( i->read_tstring_pointer(vsn3,b) ) + fFeed.invoke(fEnv); + break; + } +#undef DOLOOP + break; + default: + break; + } + if ( memory ) { + ::operator delete(memory); + } +} + +/// Map input streamer +void TGenCollectionStreamer::ReadMap(int nElements, TBuffer &b) { + bool vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; + size_t len = fValDiff*nElements; + Value *v; + char buffer[8096], *addr, *temp; + void* memory = 0; + StreamHelper* i; + float f; + fEnv->size = nElements; + fEnv->start = (len<sizeof(buffer) ? buffer : memory=::operator new(len)); + addr = temp = (char*)fEnv->start; + fConstruct.invoke(fEnv); + for ( int loop, idx = 0; idx < nElements; ++idx ) { + addr = temp + fValDiff*idx; + v = fKey; + for ( loop=0; loop<2; loop++ ) { + i = (StreamHelper*)addr; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b >> i->s_char; break; + case kShort_t: b >> i->s_short; break; + case kInt_t: b >> i->s_int; break; + case kLong_t: b >> i->s_long; break; + case kLong64_t: b >> i->s_longlong; break; + case kFloat_t: b >> i->flt; break; + case kDouble_t: b >> i->dbl; break; + case kBOOL_t: b >> i->boolean; break; + case kUChar_t: b >> i->u_char; break; + case kUShort_t: b >> i->u_short; break; + case kUInt_t: b >> i->u_int; break; + case kULong_t: b >> i->u_long; break; + case kULong64_t: b >> i->u_longlong; break; + case kDouble32_t:b >> f; + i->dbl = double(f); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(i,v->fType); + break; + case R__BIT_ISSTRING: + i->read_std_string(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + i->set(b.ReadObjectAny(v->fType)); + break; + case G__BIT_ISPOINTER|R__BIT_ISSTRING: +#ifndef R__AIX + i->read_std_string_pointer(b); +#endif + break; + case G__BIT_ISPOINTER|R__BIT_ISTSTRING|G__BIT_ISCLASS: + i->read_tstring_pointer(vsn3,b); + break; + } + v = fVal; + addr += fValOffset; + } + } + fFeed.invoke(fEnv); + fDestruct.invoke(fEnv); + if ( memory ) { + ::operator delete(memory); + } +} + +/// Primitive output streamer +void TGenCollectionStreamer::WritePrimitives(int nElements, TBuffer &b) { + size_t len = fValDiff*nElements; + char buffer[8192]; + void* memory = 0; + StreamHelper* itm = 0; + + switch ( fSTL_type ) { + case TClassEdit::kVector: + if ( fVal->fKind != EDataType(kBOOL_t) ) { + itm = (StreamHelper*)(fEnv->start = fFirst.invoke(fEnv)); + break; + } + default: + fEnv->start = itm = (StreamHelper*) (len<sizeof(buffer) ? buffer : memory=::operator new(len)); + fCollect.invoke(fEnv); + break; + } + switch( int(fValue->fKind) ) { + case kChar_t: b.WriteFastArray(&itm->s_char , nElements); break; + case kShort_t: b.WriteFastArray(&itm->s_short , nElements); break; + case kInt_t: b.WriteFastArray(&itm->s_int , nElements); break; + case kLong_t: b.WriteFastArray(&itm->s_long , nElements); break; + case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements); break; + case kFloat_t: b.WriteFastArray(&itm->flt , nElements); break; + case kDouble_t: b.WriteFastArray(&itm->dbl , nElements); break; + case kBOOL_t: b.WriteFastArray(&itm->boolean , nElements); break; + case kUChar_t: b.WriteFastArray(&itm->u_char , nElements); break; + case kUShort_t: b.WriteFastArray(&itm->u_short , nElements); break; + case kUInt_t: b.WriteFastArray(&itm->u_int , nElements); break; + case kULong_t: b.WriteFastArray(&itm->u_long , nElements); break; + case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break; + case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",fValue->fKind); + } + if ( memory ) { + ::operator delete(memory); + } +} + +/// Object output streamer +void TGenCollectionStreamer::WriteObjects(int nElements, TBuffer &b) { + StreamHelper* itm = 0; + switch(fSTL_type) { + // Simple case: contiguous memory. get address of first, then jump. + case TClassEdit::kVector: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} + itm = (StreamHelper*)fFirst.invoke(fEnv); + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType)); + break; + case R__BIT_ISSTRING: + DOLOOP( TString(i->c_str()).Streamer(b)); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( b.WriteObjectAny(i->ptr(),fValue->fType) ); + break; + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + DOLOOP( i->write_std_string_pointer(b)); +#endif + break; + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + DOLOOP( i->write_tstring_pointer(b)); + break; + } +#undef DOLOOP + break; + + // No contiguous memory, but resize is possible + // Hence accessing objects using At(i) should be not too much an overhead + case TClassEdit::kList: + case TClassEdit::kDeque: + case TClassEdit::kMultiSet: + case TClassEdit::kSet: +#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)TGenCollectionProxy::At(idx); { x ;} ++idx;} break;} + switch (fValue->fCase) { + case G__BIT_ISCLASS: + DOLOOP( b.StreamObject(i,fValue->fType)); + case R__BIT_ISSTRING: + DOLOOP( TString(i->c_str()).Streamer(b)); + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + DOLOOP( b.WriteObjectAny(i->ptr(),fValue->fType) ); + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + DOLOOP( i->write_std_string_pointer(b)); +#endif + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + DOLOOP( i->write_tstring_pointer(b)); + } +#undef DOLOOP + break; + default: + break; + } +} + +/// Map output streamer +void TGenCollectionStreamer::WriteMap(int nElements, TBuffer &b) { + StreamHelper* i; + Value *v; + + for (int loop, idx = 0; idx < nElements; ++idx ) { + char* addr = (char*)TGenCollectionProxy::At(idx); + v = fKey; + for ( loop = 0; loop<2; ++loop ) { + i = (StreamHelper*)addr; + switch (v->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + switch( int(v->fKind) ) { + case kChar_t: b << i->s_char; break; + case kShort_t: b << i->s_short; break; + case kInt_t: b << i->s_int; break; + case kLong_t: b << i->s_long; break; + case kLong64_t: b << i->s_longlong; break; + case kFloat_t: b << i->flt; break; + case kDouble_t: b << i->dbl; break; + case kBOOL_t: b << i->boolean; break; + case kUChar_t: b << i->u_char; break; + case kUShort_t: b << i->u_short; break; + case kUInt_t: b << i->u_int; break; + case kULong_t: b << i->u_long; break; + case kULong64_t: b << i->u_longlong; break; + case kDouble32_t:b << float(i->dbl); break; + case kchar: + case kNoType_t: + case kOther_t: + Error("TGenCollectionStreamer","fType %d is not supported yet!\n",v->fKind); + } + break; + case G__BIT_ISCLASS: + b.StreamObject(i,v->fType); + break; + case R__BIT_ISSTRING: + TString(i->c_str()).Streamer(b); + break; + case G__BIT_ISPOINTER|G__BIT_ISCLASS: + b.WriteObjectAny(i->ptr(),v->fType); + break; + case R__BIT_ISSTRING|G__BIT_ISPOINTER: +#ifndef R__AIX + i->write_std_string_pointer(b); +#endif + break; + case R__BIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: + i->write_tstring_pointer(b); + break; + } + addr += fValOffset; + v = fVal; + } + } +} + +/// TClassStreamer IO overload +void TGenCollectionStreamer::Streamer(TBuffer &b) { + if ( b.IsReading() ) { //Read mode + int nElements = 0; + b >> nElements; + if ( fEnv->object ) { + TGenCollectionProxy::Clear("force"); + } + if ( nElements > 0 ) { + switch(fSTL_type) { + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + case TClassEdit::kMultiSet: + case TClassEdit::kSet: + switch (fValue->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + ReadPrimitives(nElements, b); + return; + default: + ReadObjects(nElements, b); + return; + } + break; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + ReadMap(nElements, b); + break; + } + } + } + else { // Write case + int nElements = fEnv->object ? *(size_t*)fSize.invoke(fEnv) : 0; + b << nElements; + if ( nElements > 0 ) { + switch(fSTL_type) { + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + case TClassEdit::kMultiSet: + case TClassEdit::kSet: + switch (fValue->fCase) { + case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way + case G__BIT_ISENUM: + WritePrimitives(nElements, b); + return; + default: + WriteObjects(nElements, b); + return; + } + break; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + WriteMap(nElements, b); + break; + } + } + } +} diff --git a/meta/src/TClass.cxx b/meta/src/TClass.cxx index 5a8df77b44a..4c39f29aa3e 100644 --- a/meta/src/TClass.cxx +++ b/meta/src/TClass.cxx @@ -1,4 +1,4 @@ -// @(#)root/meta:$Name: $:$Id: TClass.cxx,v 1.152 2004/10/07 17:07:56 brun Exp $ +// @(#)root/meta:$Name: $:$Id: TClass.cxx,v 1.153 2004/10/29 16:07:32 rdm Exp $ // Author: Rene Brun 07/01/95 /************************************************************************* @@ -52,8 +52,8 @@ #include "TVirtualUtilPad.h" #include "TPluginManager.h" #include "TStreamer.h" +#include "TCollectionProxy.h" #include "TVirtualCollectionProxy.h" -#include "TEmulatedVectorProxy.h" #ifndef WIN32 extern long G__globalvarpointer; @@ -682,24 +682,11 @@ void TClass::Init(const char *name, Version_t cversion, Int_t stl = TClassEdit::IsSTLCont(GetName(), 0); if ( stl ) { - - // We have a TClass for an STL container. - if (fStreamer==0) { - // Need a factory! - switch ( stl ) { - case -1: - case 1: {// vector - fStreamer = new TEmulatedVectorProxy( this ); - fCollectionProxy = new TEmulatedVectorProxy( this ); - fSizeof = fCollectionProxy->Sizeof(); - break; - } - case 2: {// list - // fStreamer = new TEmulatedListProxy( this ); - break; - } - } - } + fCollectionProxy = TCollectionProxy::genEmulatedProxy( GetName() ); + fSizeof = fCollectionProxy->Sizeof(); + if (fStreamer==0) { + fStreamer = TCollectionProxy::genEmulatedClassStreamer( GetName() ); + } } } diff --git a/meta/src/TGenericClassInfo.cxx b/meta/src/TGenericClassInfo.cxx index 9aa566651aa..2a21d893de0 100644 --- a/meta/src/TGenericClassInfo.cxx +++ b/meta/src/TGenericClassInfo.cxx @@ -1,4 +1,4 @@ -// @(#)root/meta:$Name: $:$Id: TGenericClassInfo.cxx,v 1.5 2004/01/10 10:52:30 brun Exp $ +// @(#)root/meta:$Name: $:$Id: TGenericClassInfo.cxx,v 1.6 2004/07/30 19:09:51 brun Exp $ // Author: Philippe Canal 08/05/2002 /************************************************************************* @@ -127,6 +127,7 @@ namespace ROOT { fClass->SetNewArray(fNewArray); fClass->SetDelete(fDelete); fClass->SetDeleteArray(fDeleteArray); + fClass->SetDestructor(fDestructor); fClass->AdoptStreamer(fStreamer); fStreamer = 0; if (fCollectionProxy) fClass->CopyCollectionProxy(*fCollectionProxy); fClass->SetClassSize(fSizeof); diff --git a/test/TBench.cxx b/test/TBench.cxx index a2b1c977dfd..a0c2739904a 100644 --- a/test/TBench.cxx +++ b/test/TBench.cxx @@ -8,6 +8,7 @@ #include "TClass.h" //the next include must be the last one on systems like Windows/NT #include "TBench.h" +#include "Riostream.h" THit hit; #ifdef R__WIN32 @@ -15,14 +16,42 @@ THit hit; #else const char *demofile = "/tmp/bench.root"; #endif + const char* demofile_name(const char* tit) { + static std::string fn; +#ifdef R__WIN32 + fn = "$TMP/bench."; +#else + fn = "/tmp/bench."; +#endif + fn += tit; + fn += ".root"; + return fn.c_str(); + } +namespace { + struct Counter { + std::string name; + int count; + Counter(const std::string& n) : name(n), count(0) {} + ~Counter() { + print(); + } + void print(const std::string& msg="") { + cout << msg << " --- Counter: " << name << " " << count << endl; + } + }; +} + +Counter hitCount("THit"); //------------------------------------------------------------- ClassImp(THit) //------------------------------------------------------------- THit::THit() { fPulses = 0; + hitCount.count++; } THit::THit(const THit &hit) { + hitCount.count++; fX = hit.fX; fY = hit.fY; fZ = hit.fZ; @@ -35,12 +64,29 @@ THit::THit(const THit &hit) { for (int j=0;j<fNpulses;j++) fPulses[j] = hit.fPulses[j]; } +THit& THit::operator=(const THit& hit) { + fX = hit.fX; + fY = hit.fY; + fZ = hit.fZ; + for (Int_t i=0;i<10;i++) fTime[i] = hit.fTime[i]; + fPulses = 0; + fNpulses = hit.fNpulses; + if (fNpulses == 0) return *this; + if (hit.fPulses == 0) return *this; + if ( fPulses ) delete [] fPulses; + fPulses = new int[fNpulses]; + for (int j=0;j<fNpulses;j++) fPulses[j] = hit.fPulses[j]; + return *this; +} + THit::THit(int t) { + hitCount.count++; fPulses = 0; Set(t); } THit::~THit() { + hitCount.count--; if (fPulses) delete [] fPulses; fPulses = 0; } @@ -81,6 +127,7 @@ ClassImp(TObjHit) TObjHit::TObjHit() :THit() {} TObjHit::TObjHit(int t) :THit(t) {} + //------------------------------------------------------------- ClassImp(TSTLhit) //------------------------------------------------------------- @@ -95,6 +142,8 @@ TSTLhit::TSTLhit(Int_t nmax) } TSTLhit::~TSTLhit() { + Clear(); + hitCount.print(); } void TSTLhit::Clear(Option_t *) @@ -117,7 +166,7 @@ Int_t TSTLhit::MakeTree(int mode, int nevents, int compression, int split, float TTree *T=0; TSTLhit *top = this; if (mode > 0) { - f = new TFile(demofile,"recreate","STLhit",compression); + f = new TFile(demofile_name("TSTLhit"),"recreate","STLhit",compression); T = new TTree("T","Demo tree"); T->Branch("event","TSTLhit",&top,64000,split); } @@ -129,7 +178,7 @@ Int_t TSTLhit::MakeTree(int mode, int nevents, int compression, int split, float if (mode == 0) return 0; T->Write(); delete f; - f = new TFile(demofile); + f = new TFile(demofile_name("TSTLhit")); Int_t nbytes = f->GetEND(); cx = f->GetCompressionFactor(); delete f; @@ -139,7 +188,7 @@ Int_t TSTLhit::MakeTree(int mode, int nevents, int compression, int split, float Int_t TSTLhit::ReadTree() { TSTLhit *top = this; - TFile *f = new TFile(demofile); + TFile *f = new TFile(demofile_name("TSTLhit")); TTree *T = (TTree*)f->Get("T"); T->SetBranchAddress("event",&top); Int_t nevents = (Int_t)T->GetEntries(); @@ -154,46 +203,117 @@ Int_t TSTLhit::ReadTree() //------------------------------------------------------------- -ClassImp(TSTLhitStar) +ClassImp(TSTLhitList) //------------------------------------------------------------- -TSTLhitStar::TSTLhitStar() +TSTLhitList::TSTLhitList() { } -TSTLhitStar::TSTLhitStar(Int_t nmax) +TSTLhitList::TSTLhitList(Int_t nmax) { fNhits = nmax; - fList2.reserve(nmax); } -TSTLhitStar::~TSTLhitStar() { +TSTLhitList::~TSTLhitList() { + Clear(); + hitCount.print(); } -void TSTLhitStar::Clear(Option_t *) +void TSTLhitList::Clear(Option_t *) { - for (vector<THit*>::iterator it = fList2.begin(); it<fList2.end(); it++) { - delete (*it); + fList1.erase(fList1.begin(),fList1.end()); +} + +void TSTLhitList::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + hit.Set(j); + fList1.push_back(hit); } - fList2.erase(fList2.begin(),fList2.end()); } -void TSTLhitStar::MakeEvent(int /*ievent*/) +Int_t TSTLhitList::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitList *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitList"),"recreate","STLhit",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitList",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitList")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitList::ReadTree() +{ + TSTLhitList *top = this; + TFile *f = new TFile(demofile_name("TSTLhitList")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + +//------------------------------------------------------------- +ClassImp(TSTLhitDeque) +//------------------------------------------------------------- +TSTLhitDeque::TSTLhitDeque() +{ +} + +TSTLhitDeque::TSTLhitDeque(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitDeque::~TSTLhitDeque() { + Clear(); + hitCount.print(); +} + +void TSTLhitDeque::Clear(Option_t *) +{ + fList1.erase(fList1.begin(),fList1.end()); +} + +void TSTLhitDeque::MakeEvent(int /*ievent*/) { Clear(); for (Int_t j=0; j<fNhits; j++) { - fList2.push_back(new THit(j)); + hit.Set(j); + fList1.push_back(hit); } } -Int_t TSTLhitStar::MakeTree(int mode, int nevents, int compression, int split, float &cx) +Int_t TSTLhitDeque::MakeTree(int mode, int nevents, int compression, int split, float &cx) { TFile *f=0; TTree *T=0; - TSTLhitStar *top = this; + TSTLhitDeque *top = this; if (mode > 0) { - f = new TFile(demofile,"recreate","STLhitStar",compression); + f = new TFile(demofile_name("TSTLhitDeque"),"recreate","STLhit",compression); T = new TTree("T","Demo tree"); - T->Branch("event","TSTLhitStar",&top,64000,split); + T->Branch("event","TSTLhitDeque",&top,64000,split); } for (int ievent=0; ievent<nevents; ievent++) { MakeEvent(ievent); @@ -203,17 +323,163 @@ Int_t TSTLhitStar::MakeTree(int mode, int nevents, int compression, int split, f if (mode == 0) return 0; T->Write(); delete f; - f = new TFile(demofile); + f = new TFile(demofile_name("TSTLhitDeque")); Int_t nbytes = f->GetEND(); cx = f->GetCompressionFactor(); delete f; return nbytes; } -Int_t TSTLhitStar::ReadTree() +Int_t TSTLhitDeque::ReadTree() { - TSTLhitStar *top = this; - TFile *f = new TFile(demofile); + TSTLhitDeque *top = this; + TFile *f = new TFile(demofile_name("TSTLhitDeque")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + + +//------------------------------------------------------------- +ClassImp(TSTLhitSet) +//------------------------------------------------------------- +TSTLhitSet::TSTLhitSet() +{ +} + +TSTLhitSet::TSTLhitSet(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitSet::~TSTLhitSet() { + Clear(); + hitCount.print(); +} + +void TSTLhitSet::Clear(Option_t *) +{ + fList1.erase(fList1.begin(),fList1.end()); +} + +void TSTLhitSet::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + hit.Set(j); + fList1.insert(hit); + } +} + +Int_t TSTLhitSet::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitSet *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitSet"),"recreate","STLhit",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitSet",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitSet")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitSet::ReadTree() +{ + TSTLhitSet *top = this; + TFile *f = new TFile(demofile_name("TSTLhitSet")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + + +//------------------------------------------------------------- +ClassImp(TSTLhitMultiset) +//------------------------------------------------------------- +TSTLhitMultiset::TSTLhitMultiset() +{ +} + +TSTLhitMultiset::TSTLhitMultiset(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitMultiset::~TSTLhitMultiset() { + Clear(); + hitCount.print(); +} + +void TSTLhitMultiset::Clear(Option_t *) +{ + fList1.erase(fList1.begin(),fList1.end()); +} + +void TSTLhitMultiset::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + hit.Set(j); + fList1.insert(hit); + } +} + +Int_t TSTLhitMultiset::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitMultiset *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitMultiset"),"recreate","STLhit",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitMultiset",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitMultiset")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitMultiset::ReadTree() +{ + TSTLhitMultiset *top = this; + TFile *f = new TFile(demofile_name("TSTLhitMultiset")); TTree *T = (TTree*)f->Get("T"); T->SetBranchAddress("event",&top); Int_t nevents = (Int_t)T->GetEntries(); @@ -227,6 +493,824 @@ Int_t TSTLhitStar::ReadTree() } +//------------------------------------------------------------- +ClassImp(TSTLhitMap) +//------------------------------------------------------------- +TSTLhitMap::TSTLhitMap() +{ +} + +TSTLhitMap::TSTLhitMap(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitMap::~TSTLhitMap() { + Clear(); + hitCount.print(); +} + +void TSTLhitMap::Clear(Option_t *) +{ + fList1.clear(); +} + +void TSTLhitMap::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + hit.Set(j); + fList1.insert(std::make_pair(j,hit)); + } +} + +Int_t TSTLhitMap::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitMap *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitMap"),"recreate","STLhit",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitMap",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitMap")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitMap::ReadTree() +{ + TSTLhitMap *top = this; + TFile *f = new TFile(demofile_name("TSTLhitMap")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + + +//------------------------------------------------------------- +ClassImp(TSTLhitMultiMap) +//------------------------------------------------------------- +TSTLhitMultiMap::TSTLhitMultiMap() +{ +} + +TSTLhitMultiMap::TSTLhitMultiMap(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitMultiMap::~TSTLhitMultiMap() { + Clear(); + hitCount.print(); +} + +void TSTLhitMultiMap::Clear(Option_t *) +{ + fList1.clear(); +} + +void TSTLhitMultiMap::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + hit.Set(j); + std::pair <const int, THit> temp(j,hit); + fList1.insert(temp); + } +} + +Int_t TSTLhitMultiMap::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitMultiMap *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitMultiMap"),"recreate","STLhit",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitMultiMap",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitMultiMap")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitMultiMap::ReadTree() +{ + TSTLhitMultiMap *top = this; + TFile *f = new TFile(demofile_name("TSTLhitMultiMap")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + +#if 0 +//------------------------------------------------------------- +ClassImp(TSTLhitHashSet) +//------------------------------------------------------------- +TSTLhitHashSet::TSTLhitHashSet() +{ +} + +TSTLhitHashSet::TSTLhitHashSet(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitHashSet::~TSTLhitHashSet() { + Clear(); + hitCount.print(); +} + +void TSTLhitHashSet::Clear(Option_t *) +{ + fList1.erase(fList1.begin(),fList1.end()); +} + +void TSTLhitHashSet::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + hit.Set(j); + fList1.insert(hit); + } +} + +Int_t TSTLhitHashSet::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitHashSet *top = this; + if (mode > 0) { + f = new TFile(demofile,"recreate","STLhit",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitHashSet",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitHashSet::ReadTree() +{ + TSTLhitHashSet *top = this; + TFile *f = new TFile(demofile); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + + +//------------------------------------------------------------- +ClassImp(TSTLhitHashMultiSet) +//------------------------------------------------------------- +TSTLhitHashMultiSet::TSTLhitHashMultiSet() +{ +} + +TSTLhitHashMultiSet::TSTLhitHashMultiSet(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitHashMultiSet::~TSTLhitHashMultiSet() { + Clear(); + hitCount.print(); +} + +void TSTLhitHashMultiSet::Clear(Option_t *) +{ + fList1.erase(fList1.begin(),fList1.end()); +} + +void TSTLhitHashMultiSet::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + hit.Set(j); + fList1.insert(hit); + } +} + +Int_t TSTLhitHashMultiSet::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitHashMultiSet *top = this; + if (mode > 0) { + f = new TFile(demofile,"recreate","STLhit",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitHashMultiSet",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitHashMultiSet::ReadTree() +{ + TSTLhitHashMultiSet *top = this; + TFile *f = new TFile(demofile); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} +#endif + +//------------------------------------------------------------- +ClassImp(TSTLhitStar) +//------------------------------------------------------------- +TSTLhitStar::TSTLhitStar() +{ +} + +TSTLhitStar::TSTLhitStar(Int_t nmax) +{ + fNhits = nmax; + fList2.reserve(nmax); +} + +TSTLhitStar::~TSTLhitStar() { + Clear(); + hitCount.print(); +} + +void TSTLhitStar::Clear(Option_t *) +{ + for (vector<THit*>::iterator it = fList2.begin(); it<fList2.end(); it++) { + delete (*it); + } + fList2.erase(fList2.begin(),fList2.end()); + //hitCount.print("Clear"); +} + +void TSTLhitStar::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + fList2.push_back(new THit(j)); + } +} + +Int_t TSTLhitStar::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitStar *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitStar"),"recreate","STLhitStar",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitStar",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitStar")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitStar::ReadTree() +{ + TSTLhitStar *top = this; + TFile *f = new TFile(demofile_name("TSTLhitStar")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + +//------------------------------------------------------------- +ClassImp(TSTLhitStarList) +//------------------------------------------------------------- +TSTLhitStarList::TSTLhitStarList() +{ +} + +TSTLhitStarList::TSTLhitStarList(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitStarList::~TSTLhitStarList() { + Clear(); + hitCount.print(); +} + +void TSTLhitStarList::Clear(Option_t *) +{ + for (list<THit*>::iterator it = fList2.begin(); it!=fList2.end(); it++) { + delete (*it); + } + fList2.erase(fList2.begin(),fList2.end()); +} + +void TSTLhitStarList::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + fList2.push_back(new THit(j)); + } +} + +Int_t TSTLhitStarList::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitStarList *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitStarList"),"recreate","STLhitStar",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitStarList",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitStarList")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitStarList::ReadTree() +{ + TSTLhitStarList *top = this; + TFile *f = new TFile(demofile_name("TSTLhitStarList")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + +//------------------------------------------------------------- +ClassImp(TSTLhitStarDeque) +//------------------------------------------------------------- +TSTLhitStarDeque::TSTLhitStarDeque() +{ +} + +TSTLhitStarDeque::TSTLhitStarDeque(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitStarDeque::~TSTLhitStarDeque() { + Clear(); + hitCount.print(); +} + +void TSTLhitStarDeque::Clear(Option_t *) +{ + for (deque<THit*>::iterator it = fList2.begin(); it!=fList2.end(); it++) { + delete (*it); + } + fList2.erase(fList2.begin(),fList2.end()); +} + +void TSTLhitStarDeque::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + fList2.push_back(new THit(j)); + } +} + +Int_t TSTLhitStarDeque::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitStarDeque *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitStarDeque"),"recreate","STLhitStar",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitStarDeque",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitStarDeque")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitStarDeque::ReadTree() +{ + TSTLhitStarDeque *top = this; + TFile *f = new TFile(demofile_name("TSTLhitStarDeque")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + +//------------------------------------------------------------- +ClassImp(TSTLhitStarSet) +//------------------------------------------------------------- +TSTLhitStarSet::TSTLhitStarSet() +{ +} + +TSTLhitStarSet::TSTLhitStarSet(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitStarSet::~TSTLhitStarSet() { + Clear(); + hitCount.print(); +} + +void TSTLhitStarSet::Clear(Option_t *) +{ + for (set<THit*>::iterator it = fList2.begin(); it!=fList2.end(); it++) { + delete (*it); + } + fList2.erase(fList2.begin(),fList2.end()); +} + +void TSTLhitStarSet::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + fList2.insert(new THit(j)); + } +} + +Int_t TSTLhitStarSet::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitStarSet *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitStarSet"),"recreate","STLhitStar",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitStarSet",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitStarSet")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitStarSet::ReadTree() +{ + TSTLhitStarSet *top = this; + TFile *f = new TFile(demofile_name("TSTLhitStarSet")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + +//------------------------------------------------------------- +ClassImp(TSTLhitStarMultiSet) +//------------------------------------------------------------- +TSTLhitStarMultiSet::TSTLhitStarMultiSet() +{ +} + +TSTLhitStarMultiSet::TSTLhitStarMultiSet(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitStarMultiSet::~TSTLhitStarMultiSet() { + Clear(); + hitCount.print(); +} + +void TSTLhitStarMultiSet::Clear(Option_t *) +{ + for (multiset<THit*>::iterator it = fList2.begin(); it!=fList2.end(); it++) { + delete (*it); + } + fList2.erase(fList2.begin(),fList2.end()); +} + +void TSTLhitStarMultiSet::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + fList2.insert(new THit(j)); + } +} + +Int_t TSTLhitStarMultiSet::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitStarMultiSet *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitStarMultiSet"),"recreate","STLhitStar",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitStarMultiSet",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitStarMultiSet")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitStarMultiSet::ReadTree() +{ + TSTLhitStarMultiSet *top = this; + TFile *f = new TFile(demofile_name("TSTLhitStarMultiSet")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + + +//------------------------------------------------------------- +ClassImp(TSTLhitStarMap) +//------------------------------------------------------------- +TSTLhitStarMap::TSTLhitStarMap() +{ +} + +TSTLhitStarMap::TSTLhitStarMap(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitStarMap::~TSTLhitStarMap() { + Clear(); + hitCount.print(); +} + +void TSTLhitStarMap::Clear(Option_t *) +{ + for (map<int,THit*>::iterator it = fList2.begin(); it!=fList2.end(); it++) { + delete (*it).second; + } + fList2.clear(); +} + +void TSTLhitStarMap::MakeEvent(int /*ievent*/) +{ +// hitCount.print("1"); + Clear(); +// hitCount.print("1.1"); + for (Int_t j=0; j<fNhits; j++) { + fList2.insert(std::make_pair(j,new THit(j))); + } +// hitCount.print("1.2"); +} + +Int_t TSTLhitStarMap::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitStarMap *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitStarMap"),"recreate","STLhitStar",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitStarMap",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitStarMap")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitStarMap::ReadTree() +{ + TSTLhitStarMap *top = this; + TFile *f = new TFile(demofile_name("TSTLhitStarMap")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + +//------------------------------------------------------------- +ClassImp(TSTLhitStarMultiMap) +//------------------------------------------------------------- +TSTLhitStarMultiMap::TSTLhitStarMultiMap() +{ +} + +TSTLhitStarMultiMap::TSTLhitStarMultiMap(Int_t nmax) +{ + fNhits = nmax; +} + +TSTLhitStarMultiMap::~TSTLhitStarMultiMap() { + Clear(); + hitCount.print(); +} + +void TSTLhitStarMultiMap::Clear(Option_t *) +{ + for (multimap<int,THit*>::iterator it = fList2.begin(); it!=fList2.end(); it++) { + delete (*it).second; + } + fList2.clear(); +} + +void TSTLhitStarMultiMap::MakeEvent(int /*ievent*/) +{ + Clear(); + for (Int_t j=0; j<fNhits; j++) { + std::pair<const int,THit*> temp(j,new THit(j)); + fList2.insert(temp); + } +} + +Int_t TSTLhitStarMultiMap::MakeTree(int mode, int nevents, int compression, int split, float &cx) +{ + TFile *f=0; + TTree *T=0; + TSTLhitStarMultiMap *top = this; + if (mode > 0) { + f = new TFile(demofile_name("TSTLhitStarMultiMap"),"recreate","STLhitStar",compression); + T = new TTree("T","Demo tree"); + T->Branch("event","TSTLhitStarMultiMap",&top,64000,split); + } + for (int ievent=0; ievent<nevents; ievent++) { + MakeEvent(ievent); + if (mode > 0) T->Fill(); + } + + if (mode == 0) return 0; + T->Write(); + delete f; + f = new TFile(demofile_name("TSTLhitStarMultiMap")); + Int_t nbytes = f->GetEND(); + cx = f->GetCompressionFactor(); + delete f; + return nbytes; +} + +Int_t TSTLhitStarMultiMap::ReadTree() +{ + TSTLhitStarMultiMap *top = this; + TFile *f = new TFile(demofile_name("TSTLhitStarMultiMap")); + TTree *T = (TTree*)f->Get("T"); + T->SetBranchAddress("event",&top); + Int_t nevents = (Int_t)T->GetEntries(); + Int_t nbytes = 0; + for (int ievent=0; ievent<nevents; ievent++) { + nbytes += T->GetEntry(ievent); + Clear(); + } + delete f; + return nbytes; +} + //------------------------------------------------------------- ClassImp(TCloneshit) //------------------------------------------------------------- @@ -243,6 +1327,8 @@ TCloneshit::TCloneshit(Int_t nmax) } TCloneshit::~TCloneshit() { + Clear(); + hitCount.print(); } void TCloneshit::Clear(Option_t *) diff --git a/test/TBench.h b/test/TBench.h index dcf91ef0216..6874aaee93c 100644 --- a/test/TBench.h +++ b/test/TBench.h @@ -2,14 +2,36 @@ #define ROOT_TBENCH #include "TClonesArray.h" - +namespace stdext {}; #include <vector> +#include <deque> +#include <list> +#include <set> +#include <map> + #ifndef R__GLOBALSTL #ifndef WIN32 using std::vector; +using std::list; +using std::deque; +using std::set; +using std::multiset; +using std::map; +using std::multimap; #else using namespace std; +using namespace stdext; +#endif #endif + +#ifdef __CINT__ +template<class a,class b,class c> class hash_map : public map<a,b,c> {}; +template<class a,class b> class hash_set : public set<a,b> {}; +template<class a,class b,class c> class hash_multimap : public multimap<a,b,c> {}; +template<class a,class b> class hash_multiset : public multiset<a,b> {}; +#else +//#include <hash_map> +//#include <hash_set> #endif //------------------------------------------------------------- @@ -30,12 +52,28 @@ public: void Set (int time); inline int Get(int i) { return fTime[i]; } - + bool operator==(const THit& c) const { return this==&c;} + bool operator<(const THit& c) const { return this<&c;} + THit& operator=(const THit& c); friend TBuffer &operator<<(TBuffer &b, const THit *hit); ClassDef(THit,1) // the hit class }; +namespace stdext { + template<class T> static inline size_t __gnu_cxx_hash_obj(const T& __o) { + unsigned long __h = 0; + const char* s = (const char*)&__o; + for (size_t i=0; i<sizeof(T); ++s, ++i) + __h = 5*__h + *s; + return size_t(__h); + } + + template <class _Key> struct hash { }; + inline size_t hash_value(const THit& s) { + return __gnu_cxx_hash_obj(s); + } +} #if defined R__TEMPLATE_OVERLOAD_BUG template <> #endif @@ -62,7 +100,7 @@ public: class TSTLhit { protected: Int_t fNhits; - vector <THit> fList1; //|| + vector <THit> fList1; public: @@ -76,7 +114,155 @@ public: ClassDef(TSTLhit,1) // STL vector of THit }; +//------------------------------------------------------------- +class TSTLhitList { +protected: + Int_t fNhits; + list <THit> fList1; + +public: + + TSTLhitList(); + TSTLhitList(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitList(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitList,1) // STL vector of THit +}; + +//------------------------------------------------------------- +class TSTLhitDeque { +protected: + Int_t fNhits; + deque <THit> fList1; + +public: + + TSTLhitDeque(); + TSTLhitDeque(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitDeque(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitDeque,1) // STL vector of THit +}; +//------------------------------------------------------------- +class TSTLhitMultiset { +protected: + Int_t fNhits; + multiset <THit> fList1; + +public: + + TSTLhitMultiset(); + TSTLhitMultiset(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitMultiset(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitMultiset,1) // STL vector of THit +}; + +//------------------------------------------------------------- +class TSTLhitSet { +protected: + Int_t fNhits; + set <THit> fList1; + +public: + + TSTLhitSet(); + TSTLhitSet(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitSet(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitSet,1) // STL vector of THit +}; +//------------------------------------------------------------- +class TSTLhitMap { +protected: + Int_t fNhits; + map <int,THit> fList1; + +public: + + TSTLhitMap(); + TSTLhitMap(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitMap(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitMap,1) // STL vector of THit +}; +//------------------------------------------------------------- +class TSTLhitMultiMap { +protected: + Int_t fNhits; + multimap <int,THit> fList1; + +public: + + TSTLhitMultiMap(); + TSTLhitMultiMap(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitMultiMap(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitMultiMap,1) // STL vector of THit +}; +#if 0 +//------------------------------------------------------------- +class TSTLhitHashSet { +protected: + Int_t fNhits; + hash_set <THit> fList1; + +public: + + TSTLhitHashSet(); + TSTLhitHashSet(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitHashSet(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitHashSet,1) // STL vector of THit +}; +//------------------------------------------------------------- +class TSTLhitHashMultiSet { +protected: + Int_t fNhits; + hash_multiset <THit> fList1; + +public: + + TSTLhitHashMultiSet(); + TSTLhitHashMultiSet(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitHashMultiSet(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitHashMultiSet,1) // STL vector of THit +}; +#endif //------------------------------------------------------------- class TSTLhitStar { protected: @@ -95,6 +281,118 @@ public: ClassDef(TSTLhitStar,1) // STL vector of pointers to THit }; +//------------------------------------------------------------- +class TSTLhitStarList { +protected: + Int_t fNhits; + list <THit*> fList2; // + +public: + + TSTLhitStarList(); + TSTLhitStarList(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitStarList(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitStarList,1) // STL vector of pointers to THit +}; +//------------------------------------------------------------- +class TSTLhitStarDeque { +protected: + Int_t fNhits; + deque <THit*> fList2; // + +public: + + TSTLhitStarDeque(); + TSTLhitStarDeque(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitStarDeque(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitStarDeque,1) // STL vector of pointers to THit +}; + +//------------------------------------------------------------- +class TSTLhitStarSet { +protected: + Int_t fNhits; + set <THit*> fList2; // + +public: + + TSTLhitStarSet(); + TSTLhitStarSet(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitStarSet(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitStarSet,1) // STL vector of pointers to THit +}; + +//------------------------------------------------------------- +class TSTLhitStarMultiSet { +protected: + Int_t fNhits; + multiset <THit*> fList2; // + +public: + + TSTLhitStarMultiSet(); + TSTLhitStarMultiSet(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitStarMultiSet(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitStarMultiSet,1) // STL vector of pointers to THit +}; + +//------------------------------------------------------------- +class TSTLhitStarMap { +protected: + Int_t fNhits; + map <int,THit*> fList2; // + +public: + + TSTLhitStarMap(); + TSTLhitStarMap(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitStarMap(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitStarMap,1) // STL vector of pointers to THit +}; + +//------------------------------------------------------------- +class TSTLhitStarMultiMap { +protected: + Int_t fNhits; + multimap<int,THit*> fList2; // + +public: + + TSTLhitStarMultiMap(); + TSTLhitStarMultiMap(int nmax); + void Clear(Option_t *option=""); + virtual ~TSTLhitStarMultiMap(); + void MakeEvent(int ievent); + Int_t MakeTree(int mode, int nevents, int compression, int split, float &cx); + Int_t ReadTree(); + + ClassDef(TSTLhitStarMultiMap,1) // STL vector of pointers to THit +}; //------------------------------------------------------------- class TCloneshit { diff --git a/test/bench.cxx b/test/bench.cxx index e7f292d6a21..0eca104fb14 100644 --- a/test/bench.cxx +++ b/test/bench.cxx @@ -90,6 +90,7 @@ void showhist(const char *title, const char *ytitle, float a, float b, float c, boxd->SetFillStyle(3012); } + int main(int argc, char** argv) { TRint *theApp = new TRint("Rint", &argc, argv, 0, 0); @@ -103,6 +104,10 @@ int main(int argc, char** argv) //testing STL vector of THit Double_t cptot = 0; TStopwatch timer; + + //delete temp file used for the benchmark + gSystem->Exec("rm -f /tmp/bench.root"); + /// STL VECTOR timer.Start(); TSTLhit *STLhit = new TSTLhit(nhits); STLhit->MakeTree(0,nevents,0,0,cx); @@ -110,36 +115,277 @@ int main(int argc, char** argv) Double_t rt1 = timer.RealTime(); Double_t cp1 = timer.CpuTime(); cptot += cp1; - printf("1 STLhit : RT=%6.2f s Cpu=%6.2f s\n",rt1,cp1); + printf("1 vector : RT=%6.2f s Cpu=%6.2f s\n",rt1,cp1); timer.Start(kTRUE); - Int_t nbytes1 = STLhit->MakeTree(1,nevents,0,0,cx); + Int_t nbytes1 = STLhit->MakeTree(1,nevents,0,99,cx); timer.Stop(); Double_t rt2w = timer.RealTime(); Double_t cp2w = timer.CpuTime(); cptot += cp2w; - printf("2 STLhitw: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2w-rt1,cp2w-cp1,nbytes1,cx); + printf("2 vector w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2w-rt1,cp2w-cp1,nbytes1,cx); timer.Start(kTRUE); STLhit->ReadTree(); timer.Stop(); Double_t rt2r = timer.RealTime(); Double_t cp2r = timer.CpuTime(); cptot += cp2r; - printf("3 STLhitr: RT=%6.2f s Cpu=%6.2f s\n",rt2r,cp2r); + printf("3 vector r: RT=%6.2f s Cpu=%6.2f s\n",rt2r,cp2r); timer.Start(kTRUE); Float_t cx3; - Int_t nbytes3 = STLhit->MakeTree(1,nevents,1,0,cx3); + Int_t nbytes3 = STLhit->MakeTree(1,nevents,1,99,cx3); timer.Stop(); Double_t rt3w = timer.RealTime(); Double_t cp3w = timer.CpuTime(); cptot += cp3w; - printf("4 STLhitw: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3w-rt1,cp3w-cp1,nbytes3,cx3); + printf("4 vector w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3w-rt1,cp3w-cp1,nbytes3,cx3); timer.Start(kTRUE); STLhit->ReadTree(); timer.Stop(); Double_t rt3r = timer.RealTime(); Double_t cp3r = timer.CpuTime(); cptot += cp3r; - printf("5 STLhitr: RT=%6.2f s Cpu=%6.2f s\n",rt3r,cp3r); + printf("5 vector r: RT=%6.2f s Cpu=%6.2f s\n",rt3r,cp3r); + delete STLhit; + + // STL list + timer.Start(); + TSTLhitList *STLhit_list = new TSTLhitList(nhits); + STLhit_list->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1L = timer.RealTime(); + Double_t cp1L = timer.CpuTime(); + cptot += cp1L; + printf("1 list : RT=%6.2f s Cpu=%6.2f s\n",rt1L,cp1L); + timer.Start(kTRUE); + Int_t nbytes1L = STLhit_list->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wL = timer.RealTime(); + Double_t cp2wL = timer.CpuTime(); + cptot += cp2wL; + printf("2 list w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wL-rt1L,cp2wL-cp1L,nbytes1L,cx); + timer.Start(kTRUE); + STLhit_list->ReadTree(); + timer.Stop(); + Double_t rt2rL = timer.RealTime(); + Double_t cp2rL = timer.CpuTime(); + cptot += cp2rL; + printf("3 list r: RT=%6.2f s Cpu=%6.2f s\n",rt2rL,cp2rL); + timer.Start(kTRUE); + Float_t cx3L; + Int_t nbytes3L = STLhit_list->MakeTree(1,nevents,1,99,cx3L); + timer.Stop(); + Double_t rt3wL = timer.RealTime(); + Double_t cp3wL = timer.CpuTime(); + cptot += cp3wL; + printf("4 list w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wL-rt1L,cp3wL-cp1L,nbytes3L,cx3L); + timer.Start(kTRUE); + STLhit_list->ReadTree(); + timer.Stop(); + Double_t rt3rL = timer.RealTime(); + Double_t cp3rL = timer.CpuTime(); + cptot += cp3rL; + printf("5 list r: RT=%6.2f s Cpu=%6.2f s\n",rt3rL,cp3rL); + delete STLhit_list; + + // STL DEQUE + timer.Start(); + TSTLhitDeque *STLhit_deque = new TSTLhitDeque(nhits); + STLhit_deque->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1D = timer.RealTime(); + Double_t cp1D = timer.CpuTime(); + cptot += cp1D; + printf("1 deque : RT=%6.2f s Cpu=%6.2f s\n",rt1D,cp1D); + timer.Start(kTRUE); + Int_t nbytes1D = STLhit_deque->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wD = timer.RealTime(); + Double_t cp2wD = timer.CpuTime(); + cptot += cp2wD; + printf("2 deque w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wD-rt1D,cp2wD-cp1D,nbytes1D,cx); + timer.Start(kTRUE); + STLhit_deque->ReadTree(); + timer.Stop(); + Double_t rt2rD = timer.RealTime(); + Double_t cp2rD = timer.CpuTime(); + cptot += cp2rD; + printf("3 deque r: RT=%6.2f s Cpu=%6.2f s\n",rt2rD,cp2rD); + timer.Start(kTRUE); + Float_t cx3D; + Int_t nbytes3D = STLhit_deque->MakeTree(1,nevents,1,99,cx3D); + timer.Stop(); + Double_t rt3wD = timer.RealTime(); + Double_t cp3wD = timer.CpuTime(); + cptot += cp3wD; + printf("4 deque w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wD-rt1D,cp3wD-cp1D,nbytes3D,cx3D); + timer.Start(kTRUE); + STLhit_deque->ReadTree(); + timer.Stop(); + Double_t rt3rD = timer.RealTime(); + Double_t cp3rD = timer.CpuTime(); + cptot += cp3rD; + printf("5 deque r: RT=%6.2f s Cpu=%6.2f s\n",rt3rD,cp3rD); + delete STLhit_deque; + + // STL SET + timer.Start(); + TSTLhitSet *STLhit_set = new TSTLhitSet(nhits); + STLhit_set->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1S = timer.RealTime(); + Double_t cp1S = timer.CpuTime(); + cptot += cp1S; + printf("1 set : RT=%6.2f s Cpu=%6.2f s\n",rt1S,cp1S); + timer.Start(kTRUE); + Int_t nbytes1S = STLhit_set->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wS = timer.RealTime(); + Double_t cp2wS = timer.CpuTime(); + cptot += cp2wS; + printf("2 set w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wS-rt1S,cp2wS-cp1S,nbytes1S,cx); + timer.Start(kTRUE); + STLhit_set->ReadTree(); + timer.Stop(); + Double_t rt2rS = timer.RealTime(); + Double_t cp2rS = timer.CpuTime(); + cptot += cp2rS; + printf("3 set r: RT=%6.2f s Cpu=%6.2f s\n",rt2rS,cp2rS); + timer.Start(kTRUE); + Float_t cx3S; + Int_t nbytes3S = STLhit_set->MakeTree(1,nevents,1,99,cx3S); + timer.Stop(); + Double_t rt3wS = timer.RealTime(); + Double_t cp3wS = timer.CpuTime(); + cptot += cp3wS; + printf("4 set w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wS-rt1S,cp3wS-cp1S,nbytes3S,cx3S); + timer.Start(kTRUE); + STLhit_set->ReadTree(); + timer.Stop(); + Double_t rt3rS = timer.RealTime(); + Double_t cp3rS = timer.CpuTime(); + cptot += cp3rS; + printf("5 set r: RT=%6.2f s Cpu=%6.2f s\n",rt3rS,cp3rS); + delete STLhit_set; + + // STL MULTI SET + timer.Start(); + TSTLhitMultiset *STLhit_multiset = new TSTLhitMultiset(nhits); + STLhit_multiset->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1M = timer.RealTime(); + Double_t cp1M = timer.CpuTime(); + cptot += cp1M; + printf("1 multiset : RT=%6.2f s Cpu=%6.2f s\n",rt1M,cp1M); + timer.Start(kTRUE); + Int_t nbytes1M = STLhit_multiset->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wM = timer.RealTime(); + Double_t cp2wM = timer.CpuTime(); + cptot += cp2wM; + printf("2 multiset w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wM-rt1M,cp2wM-cp1M,nbytes1M,cx); + timer.Start(kTRUE); + STLhit_multiset->ReadTree(); + timer.Stop(); + Double_t rt2rM = timer.RealTime(); + Double_t cp2rM = timer.CpuTime(); + cptot += cp2rM; + printf("3 multiset r: RT=%6.2f s Cpu=%6.2f s\n",rt2rM,cp2rM); + timer.Start(kTRUE); + Float_t cx3M; + Int_t nbytes3M = STLhit_multiset->MakeTree(1,nevents,1,99,cx3M); + timer.Stop(); + Double_t rt3wM = timer.RealTime(); + Double_t cp3wM = timer.CpuTime(); + cptot += cp3wM; + printf("4 multiset w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wM-rt1M,cp3wM-cp1M,nbytes3M,cx3M); + timer.Start(kTRUE); + STLhit_multiset->ReadTree(); + timer.Stop(); + Double_t rt3rM = timer.RealTime(); + Double_t cp3rM = timer.CpuTime(); + cptot += cp3rM; + printf("5 multiset r: RT=%6.2f s Cpu=%6.2f s\n",rt3rM,cp3rM); + delete STLhit_multiset; + + // STL map + timer.Start(); + TSTLhitMap *STLhit_map = new TSTLhitMap(nhits); + STLhit_map->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1MAP = timer.RealTime(); + Double_t cp1MAP = timer.CpuTime(); + cptot += cp1MAP; + printf("1 map : RT=%6.2f s Cpu=%6.2f s\n",rt1MAP,cp1MAP); + timer.Start(kTRUE); + Int_t nbytes1MAP = STLhit_map->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wMAP = timer.RealTime(); + Double_t cp2wMAP = timer.CpuTime(); + cptot += cp2wMAP; + printf("2 map w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wMAP-rt1MAP,cp2wMAP-cp1MAP,nbytes1MAP,cx); + timer.Start(kTRUE); + STLhit_map->ReadTree(); + timer.Stop(); + Double_t rt2rMAP = timer.RealTime(); + Double_t cp2rMAP = timer.CpuTime(); + cptot += cp2rMAP; + printf("3 map r: RT=%6.2f s Cpu=%6.2f s\n",rt2rMAP,cp2rMAP); + timer.Start(kTRUE); + Float_t cx3MAP; + Int_t nbytes3MAP = STLhit_map->MakeTree(1,nevents,1,99,cx3MAP); + timer.Stop(); + Double_t rt3wMAP = timer.RealTime(); + Double_t cp3wMAP = timer.CpuTime(); + cptot += cp3wMAP; + printf("4 map w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wMAP-rt1MAP,cp3wMAP-cp1MAP,nbytes3MAP,cx3MAP); + timer.Start(kTRUE); + STLhit_map->ReadTree(); + timer.Stop(); + Double_t rt3rMAP = timer.RealTime(); + Double_t cp3rMAP = timer.CpuTime(); + cptot += cp3rMAP; + printf("5 map r: RT=%6.2f s Cpu=%6.2f s\n",rt3rMAP,cp3rMAP); + delete STLhit_map; + + // STL multimap + timer.Start(); + TSTLhitMultiMap *STLhit_multimap = new TSTLhitMultiMap(nhits); + STLhit_multimap->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1MMAP = timer.RealTime(); + Double_t cp1MMAP = timer.CpuTime(); + cptot += cp1MMAP; + printf("1 multimap : RT=%6.2f s Cpu=%6.2f s\n",rt1MMAP,cp1MMAP); + timer.Start(kTRUE); + Int_t nbytes1MMAP = STLhit_multimap->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wMMAP = timer.RealTime(); + Double_t cp2wMMAP = timer.CpuTime(); + cptot += cp2wMMAP; + printf("2 multimap w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wMMAP-rt1MMAP,cp2wMMAP-cp1MMAP,nbytes1MMAP,cx); + timer.Start(kTRUE); + STLhit_multimap->ReadTree(); + timer.Stop(); + Double_t rt2rMMAP = timer.RealTime(); + Double_t cp2rMMAP = timer.CpuTime(); + cptot += cp2rMMAP; + printf("3 multimap r: RT=%6.2f s Cpu=%6.2f s\n",rt2rMMAP,cp2rMMAP); + timer.Start(kTRUE); + Float_t cx3MMAP; + Int_t nbytes3MMAP = STLhit_multimap->MakeTree(1,nevents,1,99,cx3MMAP); + timer.Stop(); + Double_t rt3wMMAP = timer.RealTime(); + Double_t cp3wMMAP = timer.CpuTime(); + cptot += cp3wMMAP; + printf("4 multimap w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wMMAP-rt1MMAP,cp3wMMAP-cp1MMAP,nbytes3MMAP,cx3MMAP); + timer.Start(kTRUE); + STLhit_multimap->ReadTree(); + timer.Stop(); + Double_t rt3rMMAP = timer.RealTime(); + Double_t cp3rMMAP = timer.CpuTime(); + cptot += cp3rMMAP; + printf("5 multimap r: RT=%6.2f s Cpu=%6.2f s\n",rt3rMMAP,cp3rMMAP); + delete STLhit_multimap; //testing STL vector of pointers to THit timer.Start(); @@ -149,21 +395,21 @@ int main(int argc, char** argv) Double_t rt4 = timer.RealTime(); Double_t cp4 = timer.CpuTime(); cptot += cp4; - printf("6 STLhit* : RT=%6.2f s Cpu=%6.2f s\n",rt4,cp4); + printf("1 vector* : RT=%6.2f s Cpu=%6.2f s\n",rt4,cp4); timer.Start(kTRUE); Int_t nbytes5 = STLhitStar->MakeTree(1,nevents,0,99,cx); timer.Stop(); Double_t rt5w = timer.RealTime(); Double_t cp5w = timer.CpuTime(); cptot += cp5w; - printf("7 STLhit*w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt5w-rt4,cp5w-cp4,nbytes5,cx); + printf("2 vector* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt5w-rt4,cp5w-cp4,nbytes5,cx); timer.Start(kTRUE); STLhitStar->ReadTree(); timer.Stop(); Double_t rt5r = timer.RealTime(); Double_t cp5r = timer.CpuTime(); cptot += cp5r; - printf("8 STLhit*r: RT=%6.2f s Cpu=%6.2f s\n",rt5r,cp5r); + printf("3 vector* r: RT=%6.2f s Cpu=%6.2f s\n",rt5r,cp5r); timer.Start(kTRUE); Float_t cx6; Int_t nbytes6 = STLhitStar->MakeTree(1,nevents,1,99,cx6); @@ -171,15 +417,267 @@ int main(int argc, char** argv) Double_t rt6w = timer.RealTime(); Double_t cp6w = timer.CpuTime(); cptot += cp6w; - printf("9 STLhit*w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt6w-rt4,cp6w-cp4,nbytes6,cx6); + printf("4 vector* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt6w-rt4,cp6w-cp4,nbytes6,cx6); timer.Start(kTRUE); STLhitStar->ReadTree(); timer.Stop(); Double_t rt6r = timer.RealTime(); Double_t cp6r = timer.CpuTime(); cptot += cp6r; - printf("10 STLhit*r: RT=%6.2f s Cpu=%6.2f s\n",rt6r,cp6r); + printf("5 vector* r: RT=%6.2f s Cpu=%6.2f s\n",rt6r,cp6r); + delete STLhitStar; + // STL list* + timer.Start(); + TSTLhitStarList *STLhit_liststar = new TSTLhitStarList(nhits); + STLhit_liststar->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1LS = timer.RealTime(); + Double_t cp1LS = timer.CpuTime(); + cptot += cp1LS; + printf("1 list* : RT=%6.2f s Cpu=%6.2f s\n",rt1LS,cp1LS); + timer.Start(kTRUE); + Int_t nbytes1LS = STLhit_liststar->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wLS = timer.RealTime(); + Double_t cp2wLS = timer.CpuTime(); + cptot += cp2wLS; + printf("2 list* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wLS-rt1LS,cp2wLS-cp1LS,nbytes1LS,cx); + timer.Start(kTRUE); + STLhit_liststar->ReadTree(); + timer.Stop(); + Double_t rt2rLS = timer.RealTime(); + Double_t cp2rLS = timer.CpuTime(); + cptot += cp2rLS; + printf("3 list* r: RT=%6.2f s Cpu=%6.2f s\n",rt2rLS,cp2rLS); + timer.Start(kTRUE); + Float_t cx3LS; + Int_t nbytes3LS = STLhit_liststar->MakeTree(1,nevents,1,99,cx3LS); + timer.Stop(); + Double_t rt3wLS = timer.RealTime(); + Double_t cp3wLS = timer.CpuTime(); + cptot += cp3wLS; + printf("4 list* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wLS-rt1LS,cp3wLS-cp1LS,nbytes3LS,cx3LS); + timer.Start(kTRUE); + STLhit_liststar->ReadTree(); + timer.Stop(); + Double_t rt3rLS = timer.RealTime(); + Double_t cp3rLS = timer.CpuTime(); + cptot += cp3rLS; + printf("5 list* r: RT=%6.2f s Cpu=%6.2f s\n",rt3rLS,cp3rLS); + delete STLhit_liststar; + + // STL DEQUE* + timer.Start(); + TSTLhitStarDeque *STLhit_dequestar = new TSTLhitStarDeque(nhits); + STLhit_dequestar->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1DS = timer.RealTime(); + Double_t cp1DS = timer.CpuTime(); + cptot += cp1DS; + printf("1 deque* : RT=%6.2f s Cpu=%6.2f s\n",rt1DS,cp1DS); + timer.Start(kTRUE); + Int_t nbytes1DS = STLhit_dequestar->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wDS = timer.RealTime(); + Double_t cp2wDS = timer.CpuTime(); + cptot += cp2wDS; + printf("2 deque* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wDS-rt1DS,cp2wDS-cp1DS,nbytes1DS,cx); + timer.Start(kTRUE); + STLhit_dequestar->ReadTree(); + timer.Stop(); + Double_t rt2rDS = timer.RealTime(); + Double_t cp2rDS = timer.CpuTime(); + cptot += cp2rDS; + printf("3 deque* r: RT=%6.2f s Cpu=%6.2f s\n",rt2rDS,cp2rDS); + timer.Start(kTRUE); + Float_t cx3DS; + Int_t nbytes3DS = STLhit_dequestar->MakeTree(1,nevents,1,99,cx3DS); + timer.Stop(); + Double_t rt3wDS = timer.RealTime(); + Double_t cp3wDS = timer.CpuTime(); + cptot += cp3wDS; + printf("4 deque* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wDS-rt1DS,cp3wDS-cp1DS,nbytes3DS,cx3DS); + timer.Start(kTRUE); + STLhit_dequestar->ReadTree(); + timer.Stop(); + Double_t rt3rDS = timer.RealTime(); + Double_t cp3rDS = timer.CpuTime(); + cptot += cp3rDS; + printf("5 deque* r: RT=%6.2f s Cpu=%6.2f s\n",rt3rDS,cp3rDS); + delete STLhit_dequestar; + + // STL SET* + timer.Start(); + TSTLhitStarSet *STLhit_setstar = new TSTLhitStarSet(nhits); + STLhit_setstar->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1SS = timer.RealTime(); + Double_t cp1SS = timer.CpuTime(); + cptot += cp1SS; + printf("1 set* : RT=%6.2f s Cpu=%6.2f s\n",rt1SS,cp1SS); + timer.Start(kTRUE); + Int_t nbytes1SS = STLhit_setstar->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wSS = timer.RealTime(); + Double_t cp2wSS = timer.CpuTime(); + cptot += cp2wSS; + printf("2 set* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wSS-rt1SS,cp2wSS-cp1SS,nbytes1SS,cx); + timer.Start(kTRUE); + STLhit_setstar->ReadTree(); + timer.Stop(); + Double_t rt2rSS = timer.RealTime(); + Double_t cp2rSS = timer.CpuTime(); + cptot += cp2rSS; + printf("3 set* r: RT=%6.2f s Cpu=%6.2f s\n",rt2rSS,cp2rSS); + timer.Start(kTRUE); + Float_t cx3SS; + Int_t nbytes3SS = STLhit_setstar->MakeTree(1,nevents,1,99,cx3SS); + timer.Stop(); + Double_t rt3wSS = timer.RealTime(); + Double_t cp3wSS = timer.CpuTime(); + cptot += cp3wSS; + printf("4 set* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wDS-rt1DS,cp3wSS-cp1SS,nbytes3SS,cx3SS); + timer.Start(kTRUE); + STLhit_setstar->ReadTree(); + timer.Stop(); + Double_t rt3rSS = timer.RealTime(); + Double_t cp3rSS = timer.CpuTime(); + cptot += cp3rSS; + printf("5 set* : RT=%6.2f s Cpu=%6.2f s\n",rt3rSS,cp3rSS); + delete STLhit_setstar; + + // STL MULTI SET* + timer.Start(); + TSTLhitStarMultiSet *STLhit_multisetstar = new TSTLhitStarMultiSet(nhits); + STLhit_multisetstar->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1MS = timer.RealTime(); + Double_t cp1MS = timer.CpuTime(); + cptot += cp1MS; + printf("1 multiset* : RT=%6.2f s Cpu=%6.2f s\n",rt1MS,cp1MS); + timer.Start(kTRUE); + Int_t nbytes1MS = STLhit_multisetstar->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wMS = timer.RealTime(); + Double_t cp2wMS = timer.CpuTime(); + cptot += cp2wMS; + printf("2 multiset*w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wMS-rt1MS,cp2wMS-cp1MS,nbytes1MS,cx); + timer.Start(kTRUE); + STLhit_multisetstar->ReadTree(); + timer.Stop(); + Double_t rt2rMS = timer.RealTime(); + Double_t cp2rMS = timer.CpuTime(); + cptot += cp2rMS; + printf("3 multiset*r: RT=%6.2f s Cpu=%6.2f s\n",rt2rMS,cp2rMS); + timer.Start(kTRUE); + Float_t cx3MS; + Int_t nbytes3MS = STLhit_multisetstar->MakeTree(1,nevents,1,99,cx3MS); + timer.Stop(); + Double_t rt3wMS = timer.RealTime(); + Double_t cp3wMS = timer.CpuTime(); + cptot += cp3wMS; + printf("4 multiset*w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wDS-rt1DS,cp3wDS-cp1DS,nbytes3DS,cx3DS); + timer.Start(kTRUE); + STLhit_multisetstar->ReadTree(); + timer.Stop(); + Double_t rt3rMS = timer.RealTime(); + Double_t cp3rMS = timer.CpuTime(); + cptot += cp3rMS; + printf("5 multiset* : RT=%6.2f s Cpu=%6.2f s\n",rt3rMS,cp3rMS); + delete STLhit_multisetstar; + + // STL MAP* + timer.Start(); + TSTLhitStarMap *STLhit_mapstar = new TSTLhitStarMap(nhits); + STLhit_mapstar->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1MAPS = timer.RealTime(); + Double_t cp1MAPS = timer.CpuTime(); + cptot += cp1MAPS; + printf("1 map* : RT=%6.2f s Cpu=%6.2f s\n",rt1MAPS,cp1MAPS); + timer.Start(kTRUE); + Int_t nbytes1MAPS = STLhit_mapstar->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wMAPS = timer.RealTime(); + Double_t cp2wMAPS = timer.CpuTime(); + cptot += cp2wMAPS; + printf("2 map* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wMAPS-rt1MAPS,cp2wMAPS-cp1MAPS,nbytes1MAPS,cx); + timer.Start(kTRUE); +#ifndef R__ALPHA + STLhit_mapstar->ReadTree(); +#endif + timer.Stop(); + Double_t rt2rMAPS = timer.RealTime(); + Double_t cp2rMAPS = timer.CpuTime(); + cptot += cp2rMAPS; + printf("3 map* r: RT=%6.2f s Cpu=%6.2f s\n",rt2rMAPS,cp2rMAPS); + timer.Start(kTRUE); + Float_t cx3MAPS; + Int_t nbytes3MAPS = STLhit_mapstar->MakeTree(1,nevents,1,99,cx3MAPS); + timer.Stop(); + Double_t rt3wMAPS = timer.RealTime(); + Double_t cp3wMAPS = timer.CpuTime(); + cptot += cp3wMAPS; + printf("4 map* w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wMAPS-rt1MAPS,cp3wMAPS-cp1MAPS,nbytes3MAPS,cx3MAPS); + timer.Start(kTRUE); +#ifndef R__ALPHA + STLhit_mapstar->ReadTree(); +#endif + timer.Stop(); + Double_t rt3rMAPS = timer.RealTime(); + Double_t cp3rMAPS = timer.CpuTime(); + cptot += cp3rMAPS; + printf("5 map* : RT=%6.2f s Cpu=%6.2f s\n",rt3rMAPS,cp3rMAPS); + delete STLhit_mapstar; + + // STL MULTIMAP* + timer.Start(); + TSTLhitStarMultiMap *STLhit_multimapstar = new TSTLhitStarMultiMap(nhits); + STLhit_multimapstar->MakeTree(0,nevents,0,0,cx); + timer.Stop(); + Double_t rt1MMAPS = timer.RealTime(); + Double_t cp1MMAPS = timer.CpuTime(); + cptot += cp1MMAPS; + printf("1 multimap* : RT=%6.2f s Cpu=%6.2f s\n",rt1MMAPS,cp1MMAPS); + timer.Start(kTRUE); + Int_t nbytes1MMAPS = STLhit_multimapstar->MakeTree(1,nevents,0,99,cx); + timer.Stop(); + Double_t rt2wMMAPS = timer.RealTime(); + Double_t cp2wMMAPS = timer.CpuTime(); + cptot += cp2wMMAPS; + printf("2 multimap*w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt2wMMAPS-rt1MMAPS,cp2wMMAPS-cp1MMAPS,nbytes1MMAPS,cx); + timer.Start(kTRUE); +#ifndef R__ALPHA + STLhit_multimapstar->ReadTree(); +#endif + timer.Stop(); + Double_t rt2rMMAPS = timer.RealTime(); + Double_t cp2rMMAPS = timer.CpuTime(); + cptot += cp2rMMAPS; + printf("3 multimap*r: RT=%6.2f s Cpu=%6.2f s\n",rt2rMMAPS,cp2rMMAPS); + timer.Start(kTRUE); + Float_t cx3MMAPS; + Int_t nbytes3MMAPS = STLhit_multimapstar->MakeTree(1,nevents,1,99,cx3MMAPS); + timer.Stop(); + Double_t rt3wMMAPS = timer.RealTime(); + Double_t cp3wMMAPS = timer.CpuTime(); + cptot += cp3wMMAPS; + printf("4 multimap*w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt3wMAPS-rt1MAPS,cp3wMAPS-cp1MAPS,nbytes3MAPS,cx3MAPS); + timer.Start(kTRUE); +#ifndef R__ALPHA + STLhit_multimapstar->ReadTree(); +#endif + timer.Stop(); + Double_t rt3rMMAPS = timer.RealTime(); + Double_t cp3rMMAPS = timer.CpuTime(); + cptot += cp3rMMAPS; + printf("5 multimap* : RT=%6.2f s Cpu=%6.2f s\n",rt3rMMAPS,cp3rMMAPS); + delete STLhit_multimapstar; +#ifndef R__ALPHA + printf("map and multimap do not work on alpha. test is disabled\n"); +#endif + //testing TClonesArray of TObjHit deriving from THit timer.Start(); TCloneshit *Cloneshit = new TCloneshit(nhits); @@ -188,21 +686,21 @@ int main(int argc, char** argv) Double_t rt7 = timer.RealTime(); Double_t cp7 = timer.CpuTime(); cptot += cp7; - printf("11 Clones1 : RT=%6.2f s Cpu=%6.2f s\n",rt7,cp7); + printf("1 Clones1 : RT=%6.2f s Cpu=%6.2f s\n",rt7,cp7); timer.Start(kTRUE); Int_t nbytes8 = Cloneshit->MakeTree(1,nevents,0,99,cx); timer.Stop(); Double_t rt8w = timer.RealTime(); Double_t cp8w = timer.CpuTime(); cptot += cp8w; - printf("12 Clones1w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt8w-rt7,cp8w-cp7,nbytes8,cx); + printf("2 Clones1 w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt8w-rt7,cp8w-cp7,nbytes8,cx); timer.Start(kTRUE); Cloneshit->ReadTree(); timer.Stop(); Double_t rt8r = timer.RealTime(); Double_t cp8r = timer.CpuTime(); cptot += cp8r; - printf("13 Clones1r: RT=%6.2f s Cpu=%6.2f s\n",rt8r,cp8r); + printf("3 Clones1 r: RT=%6.2f s Cpu=%6.2f s\n",rt8r,cp8r); timer.Start(kTRUE); Float_t cx9; Int_t nbytes9 = Cloneshit->MakeTree(1,nevents,1,99,cx9); @@ -210,28 +708,28 @@ int main(int argc, char** argv) Double_t rt9w = timer.RealTime(); Double_t cp9w = timer.CpuTime(); cptot += cp9w; - printf("14 Clones1w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt9w-rt7,cp9w-cp7,nbytes9,cx9); + printf("4 Clones1 w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt9w-rt7,cp9w-cp7,nbytes9,cx9); timer.Start(kTRUE); Cloneshit->ReadTree(); timer.Stop(); Double_t rt9r = timer.RealTime(); Double_t cp9r = timer.CpuTime(); cptot += cp9r; - printf("15 Clones1r: RT=%6.2f s Cpu=%6.2f s\n",rt9r,cp9r); + printf("5 Clones1 r: RT=%6.2f s Cpu=%6.2f s\n",rt9r,cp9r); timer.Start(kTRUE); Int_t nbytes10 = Cloneshit->MakeTree(1,nevents,0,99,cx); timer.Stop(); Double_t rt10w = timer.RealTime(); Double_t cp10w = timer.CpuTime(); cptot += cp10w; - printf("16 Clones2w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt10w-rt7,cp10w-cp7,nbytes10,cx); + printf("6 Clones2 w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt10w-rt7,cp10w-cp7,nbytes10,cx); timer.Start(kTRUE); Cloneshit->ReadTree(); timer.Stop(); Double_t rt10r = timer.RealTime(); Double_t cp10r = timer.CpuTime(); cptot += cp10r; - printf("17 Clones2r: RT=%6.2f s Cpu=%6.2f s\n",rt10r,cp10r); + printf("7 Clones2 r: RT=%6.2f s Cpu=%6.2f s\n",rt10r,cp10r); timer.Start(kTRUE); Float_t cx11; Int_t nbytes11 = Cloneshit->MakeTree(1,nevents,1,99,cx11); @@ -239,20 +737,17 @@ int main(int argc, char** argv) Double_t rt11w = timer.RealTime(); Double_t cp11w = timer.CpuTime(); cptot += cp11w; - printf("18 Clones2w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt11w-rt7,cp11w-cp7,nbytes11,cx11); + printf("8 Clones2 w: RT=%6.2f s Cpu=%6.2f s, size= %8d bytes, cx=%5.2f\n",rt11w-rt7,cp11w-cp7,nbytes11,cx11); timer.Start(kTRUE); Cloneshit->ReadTree(); timer.Stop(); Double_t rt11r = timer.RealTime(); Double_t cp11r = timer.CpuTime(); cptot += cp11r; - printf("19 Clones2r: RT=%6.2f s Cpu=%6.2f s\n",rt11r,cp11r); + printf("9 Clones2 r: RT=%6.2f s Cpu=%6.2f s\n",rt11r,cp11r); Double_t cpref = 24.92; Double_t rootmarks = cpref*600/cptot; - //delete temp file used for the benchmark - gSystem->Exec("rm -f /tmp/bench.root"); - //print all results char line1[100], line2[100]; printf("\n"); @@ -280,28 +775,76 @@ int main(int argc, char** argv) printf("* Time to fill the structures (seconds) Reference cx Reference *\n"); printf("******************************************************************************\n"); printf("* vector<THit> %6.2f 0.98 %5.2f 3.77 *\n",cp1,cx3); + printf("* list<THit> %6.2f xxxx %5.2f xxxx *\n",cp1L,cx3L); + printf("* deque<THit> %6.2f xxxx %5.2f xxxx *\n",cp1D,cx3D); + printf("* set<THit> %6.2f xxxx %5.2f xxxx *\n",cp1S,cx3S); + printf("* multiset<THit> %6.2f xxxx %5.2f xxxx *\n",cp1M,cx3M); + printf("* map<int,THit> %6.2f xxxx %5.2f xxxx *\n",cp1MAP,cx3MAP); + printf("* multimap<int,THit> %6.2f xxxx %5.2f xxxx *\n",cp1MMAP,cx3MMAP); printf("* vector<THit*> %6.2f 0.90 %5.2f 3.78 *\n",cp4,cx6); + printf("* list<THit*> %6.2f xxxx %5.2f xxxx *\n",cp1LS,cx3LS); + printf("* deque<THit*> %6.2f xxxx %5.2f xxxx *\n",cp1DS,cx3DS); + printf("* set<THit*> %6.2f xxxx %5.2f xxxx *\n",cp1SS,cx3SS); + printf("* multiset<THit*> %6.2f xxxx %5.2f xxxx *\n",cp1MS,cx3MS); + printf("* map<int,THit*> %6.2f xxxx %5.2f xxxx *\n",cp1MAPS,cx3MAPS); + printf("* multimap<int,THit*> %6.2f xxxx %5.2f xxxx *\n",cp1MMAPS,cx3MMAPS); printf("* TClonesArray(TObjHit) %6.2f 0.74 %5.2f 5.40 *\n",cp7,cx9); printf("* TClonesArray(TObjHit) split %6.2f 0.74 %5.2f 5.40 *\n",cp7,cx11); printf("******************************************************************************\n"); printf("* Size of file in bytes comp 0 Reference comp 1 Reference *\n"); printf("******************************************************************************\n"); printf("* vector<THit> %8d 42053619 %8d 11144596 *\n",nbytes1,nbytes3); + printf("* list<THit> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1L,nbytes3L); + printf("* deque<THit> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1D,nbytes3D); + printf("* set<THit> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1S,nbytes3S); + printf("* multiset<THit> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1M,nbytes3M); + printf("* map<int,THit> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1MAP,nbytes3MAP); + printf("* multimap<int,THit> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1MMAP,nbytes3MMAP); printf("* vector<THit*> %8d 42078956 %8d 11144412 *\n",nbytes5,nbytes6); + printf("* list<THit*> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1LS,nbytes3LS); + printf("* deque<THit*> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1DS,nbytes3DS); + printf("* set<THit*> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1SS,nbytes3SS); + printf("* multiset<THit*> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1MS,nbytes3MS); + printf("* map<int,THit*> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1MAPS,nbytes3MAPS); + printf("* multimap<int,THit*> %8d xxxxxxxx %8d xxxxxxxx *\n",nbytes1MMAPS,nbytes3MMAPS); printf("* TClonesArray(TObjHit) %8d 39804763 %8d 7377591 *\n",nbytes8,nbytes9); printf("* TClonesArray(TObjHit) split %8d 39804763 %8d 7377664 *\n",nbytes10,nbytes11); printf("******************************************************************************\n"); printf("* Time to write in seconds comp 0 Reference comp 1 Reference *\n"); printf("******************************************************************************\n"); printf("* vector<THit> %6.2f 0.44 %6.2f 2.17 *\n",cp2w-cp1, cp3w-cp1); + printf("* list<THit> %6.2f xxxx %6.2f xxxx *\n",cp2wL-cp1L,cp3wL-cp1L); + printf("* deque<THit> %6.2f xxxx %6.2f xxxx *\n",cp2wD-cp1D,cp3wD-cp1D); + printf("* set<THit> %6.2f xxxx %6.2f xxxx *\n",cp2wS-cp1S,cp3wS-cp1S); + printf("* multiset<THit> %6.2f xxxx %6.2f xxxx *\n",cp2wM-cp1M,cp3wM-cp1M); + printf("* map<int,THit> %6.2f xxxx %6.2f xxxx *\n",cp2wMAP-cp1MAP,cp3wMAP-cp1MAP); + printf("* multimap<int,THit> %6.2f xxxx %6.2f xxxx *\n",cp2wMMAP-cp1MMAP,cp3wMMAP-cp1MMAP); printf("* vector<THit*> %6.2f 0.38 %6.2f 2.27 *\n",cp5w-cp1, cp6w-cp1); + printf("* list<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2wLS-cp1LS,cp3wLS-cp1LS); + printf("* deque<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2wDS-cp1DS,cp3wDS-cp1DS); + printf("* set<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2wSS-cp1SS,cp3wSS-cp1SS); + printf("* multiset<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2wMS-cp1MS,cp3wMS-cp1MS); + printf("* map<int,THit*> %6.2f xxxx %6.2f xxxx *\n",cp2wMAPS-cp1MAPS,cp3wMAPS-cp1MAPS); + printf("* multimap<int,THit*> %6.2f xxxx %6.2f xxxx *\n",cp2wMMAPS-cp1MMAPS,cp3wMMAPS-cp1MMAPS); printf("* TClonesArray(TObjHit) %6.2f 0.09 %6.2f 1.28 *\n",cp8w-cp1, cp9w-cp1); printf("* TClonesArray(TObjHit) split %6.2f 0.09 %6.2f 1.28 *\n",cp10w-cp1,cp11w-cp1); printf("******************************************************************************\n"); printf("* Time to read in seconds comp 0 Reference comp 1 Reference *\n"); printf("******************************************************************************\n"); printf("* vector<THit> %6.2f 0.68 %6.2f 1.29 *\n",cp2r,cp3r); + printf("* list<THit> %6.2f xxxx %6.2f xxxx *\n",cp2rL,cp3rL); + printf("* deque<THit> %6.2f xxxx %6.2f xxxx *\n",cp2rD,cp3rD); + printf("* set<THit> %6.2f xxxx %6.2f xxxx *\n",cp2rS,cp3rS); + printf("* multiset<THit> %6.2f xxxx %6.2f xxxx *\n",cp2rM,cp3rM); + printf("* map<int,THit> %6.2f xxxx %6.2f xxxx *\n",cp2rMAP,cp3rMAP); + printf("* multimap<int,THit> %6.2f xxxx %6.2f xxxx *\n",cp2rMMAP,cp3rMMAP); printf("* vector<THit*> %6.2f 0.65 %6.2f 1.31 *\n",cp5r,cp6r); + printf("* list<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2rLS,cp3rLS); + printf("* deque<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2rDS,cp3rDS); + printf("* set<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2rSS,cp3rSS); + printf("* multiset<THit*> %6.2f xxxx %6.2f xxxx *\n",cp2rMS,cp3rMS); + printf("* map<int,THit*> %6.2f xxxx %6.2f xxxx *\n",cp2rMAPS,cp3rMAPS); + printf("* multimap<int,THit*> %6.2f xxxx %6.2f xxxx *\n",cp2rMMAPS,cp3rMMAPS); printf("* TClonesArray(TObjHit) %6.2f 0.34 %6.2f 0.76 *\n",cp8r,cp9r); printf("* TClonesArray(TObjHit) split %6.2f 0.33 %6.2f 0.75 *\n",cp10r,cp11r); printf("******************************************************************************\n"); @@ -309,6 +852,7 @@ int main(int argc, char** argv) printf("* Estimated ROOTMARKS %8.2f 600.00 *\n",rootmarks); printf("******************************************************************************\n"); +#if 0 // show results with graphics gStyle->SetTitleH(0.12); gStyle->SetTitleW(0.8); @@ -379,6 +923,6 @@ int main(int argc, char** argv) cbench->Print(); theApp->Run(); - +#endif return 0; } diff --git a/test/benchLinkDef.h b/test/benchLinkDef.h index 35f43303c00..8f774993bd6 100644 --- a/test/benchLinkDef.h +++ b/test/benchLinkDef.h @@ -6,8 +6,26 @@ #pragma link C++ class THit!+; #pragma link C++ class TObjHit+; -#pragma link C++ class TSTLhit+; -#pragma link C++ class TSTLhitStar+; +#pragma link C++ class TSTLhit; +#pragma link C++ class TSTLhitList; +#pragma link C++ class TSTLhitDeque; +#pragma link C++ class TSTLhitSet; +#pragma link C++ class TSTLhitMultiset; +#pragma link C++ class TSTLhitMap; +#pragma link C++ class TSTLhitMultiMap; +//#pragma link C++ class TSTLhitHashSet; +//#pragma link C++ class TSTLhitHashMultiset; +#pragma link C++ class pair<int,THit>; + +#pragma link C++ class TSTLhitStar; +#pragma link C++ class TSTLhitStarList; +#pragma link C++ class TSTLhitStarDeque; +#pragma link C++ class TSTLhitStarSet; +#pragma link C++ class TSTLhitStarMultiSet; +#pragma link C++ class TSTLhitStarMap; +#pragma link C++ class TSTLhitStarMultiMap; +#pragma link C++ class pair<int,THit*>; + #pragma link C++ class TCloneshit+; #endif diff --git a/tree/src/TBranchElement.cxx b/tree/src/TBranchElement.cxx index d557906c688..ad0c367e2eb 100644 --- a/tree/src/TBranchElement.cxx +++ b/tree/src/TBranchElement.cxx @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TBranchElement.cxx,v 1.148 2004/10/17 11:55:47 brun Exp $ +// @(#)root/tree:$Name: $:$Id: TBranchElement.cxx,v 1.149 2004/10/17 20:59:58 brun Exp $ // Author: Rene Brun 14/01/2001 /************************************************************************* @@ -175,7 +175,8 @@ TBranchElement::TBranchElement(const char *bname, TStreamerInfo *sinfo, Int_t id // create sub branches if requested by splitlevel if (splitlevel > 0) { - int stl = TClassEdit::IsSTLCont(element->GetTypeName()); + const char* elem_type = element->GetTypeName(); + int stl = TClassEdit::IsSTLCont(elem_type); TClass *clm; if (element->CannotSplit()) { //printf("element: %s/%s will not be split\n",element->GetName(),element->GetTitle()); @@ -196,8 +197,8 @@ TBranchElement::TBranchElement(const char *bname, TStreamerInfo *sinfo, Int_t id } return; - } else if (!strcmp(element->GetTypeName(),"TClonesArray") || !strcmp(element->GetTypeName(),"TClonesArray*")) { - Bool_t ispointer = !strcmp(element->GetTypeName(),"TClonesArray*"); + } else if (!strcmp(elem_type,"TClonesArray") || !strcmp(elem_type,"TClonesArray*")) { + Bool_t ispointer = !strcmp(elem_type,"TClonesArray*"); TClonesArray *clones; if (ispointer) { char **ppointer = (char**)(pointer); @@ -242,9 +243,11 @@ TBranchElement::TBranchElement(const char *bname, TStreamerInfo *sinfo, Int_t id BuildTitle(name); return; - } else if (stl>=1 && stl <=2) { // case of vector<> or list<> + } else if ( (stl>= TClassEdit::kVector && stl<= TClassEdit::kMultiSet) || + (stl>=-TClassEdit::kMultiSet && stl<=-TClassEdit::kVector) ) { + // case of vector<>, list<> deque<>, set<>, multiset<> - TClass *contCl = gROOT->GetClass(element->GetTypeName()); + TClass *contCl = gROOT->GetClass(elem_type); fCollProxy = contCl->GetCollectionProxy()->Generate(); @@ -252,25 +255,15 @@ TBranchElement::TBranchElement(const char *bname, TStreamerInfo *sinfo, Int_t id // See if we can split: Bool_t cansplit = kTRUE; - if (clm==0) { - cansplit = kFALSE; - } else if (clm==TString::Class() || clm==gROOT->GetClass("string")) { - cansplit = kFALSE; - } else if (fCollProxy->HasPointers()) { - cansplit = kFALSE; - } else if ( !clm->CanSplit() ) { - cansplit = kFALSE; - } else if ( clm->GetCollectionProxy() != 0 ) { - // A collection was stored in a collection, we do not know how to split it. cansplit = kFALSE; } @@ -312,17 +305,17 @@ TBranchElement::TBranchElement(const char *bname, TStreamerInfo *sinfo, Int_t id return; } - } else if (!strchr(element->GetTypeName(),'*') && + } else if (!strchr(elem_type,'*') && (fStreamerType == TStreamerInfo::kObject || fStreamerType == TStreamerInfo::kAny)) { // ===> create sub branches for members that are classes fType = 2; - clm = gROOT->GetClass(element->GetTypeName()); + clm = gROOT->GetClass(elem_type); if (Unroll(name,clm,clm,basketsize,splitlevel,0) >= 0) return; } } - TLeaf *leaf = new TLeafElement(GetTitle(),fID, fStreamerType); + TLeaf *leaf = new TLeafElement(GetTitle(),fID, fStreamerType); leaf->SetTitle(GetTitle()); leaf->SetBranch(this); fNleaves = 1; @@ -1168,14 +1161,35 @@ Int_t TBranchElement::GetEntry(Long64_t entry, Int_t getall) //one must always read the branch counter. //In the case when one reads consecutively twice the same entry, //the user may have cleared the TClonesArray between the 2 GetEntry - if (fType == 3 || fType == 4) nbytes += TBranch::GetEntry(entry, getall); - - Int_t nb; - for (Int_t i=0;i<nbranches;i++) { - TBranch *branch = (TBranch*)fBranches[i]; - nb = branch->GetEntry(entry, getall); - if (nb < 0) return nb; - nbytes += nb; + if ( fType == 3 || fType == 4 ) { + nbytes += TBranch::GetEntry(entry, getall); + } + if ( fType == 4) { + // Note: Proxy-helper needs to "embrace" the entire + // streaming of this STL container if the container + // is a set/multiset/map/multimap (what we do not + // know here). + // For vector/list/deque Allocate == Resize + // and Commit == noop. + // TODO: Exception safety a la TPushPop + TVirtualCollectionProxy* proxy = GetCollectionProxy(); + TVirtualCollectionProxy::TPushPop helper(proxy,fAddress); + void* env = proxy->Allocate(fNdata,true); + for (Int_t i=0;i<nbranches;i++) { + TBranch *branch = (TBranch*)fBranches[i]; + Int_t nb = branch->GetEntry(entry, getall); + if (nb < 0) return nb; + nbytes += nb; + } + proxy->Commit(env); + } + else { + for (Int_t i=0;i<nbranches;i++) { + TBranch *branch = (TBranch*)fBranches[i]; + Int_t nb = branch->GetEntry(entry, getall); + if (nb < 0) return nb; + nbytes += nb; + } } } else { //terminal branch @@ -1684,8 +1698,6 @@ void TBranchElement::ReadLeaves(TBuffer &b) } fNdata = n; if (!fObject) return; - TVirtualCollectionProxy::TPushPop helper(GetCollectionProxy(),fAddress); - fCollProxy->Resize(fNdata,true); } else if (fType == 41) { // sub branch of an STL class //Error("ReadLeaves","STL split mode not yet implemented (error 2)\n"); //char **ppointer = (char**)fAddress; @@ -2279,13 +2291,12 @@ Int_t TBranchElement::Unroll(const char *name, TClass *cltop, TClass *cl,Int_t b fBranches.Add(branch); } } else if (elem->IsA() == TStreamerSTL::Class() && !elem->IsaPointer()) { + // here all STL classes are handled Int_t subSplitlevel = splitlevel-1; - if (elem->CannotSplit()) { subSplitlevel = 0; } - - char *pointer = fBranchPointer + offset; + char* pointer = fBranchPointer + offset; branch = new TBranchElement(branchname,info,jd,/* 0 */ pointer ,basketsize,subSplitlevel,btype); branch->SetParentName(cltop->GetName()); fBranches.Add(branch); diff --git a/tree/src/TTree.cxx b/tree/src/TTree.cxx index 6b202cb8acd..683c6d16eb2 100644 --- a/tree/src/TTree.cxx +++ b/tree/src/TTree.cxx @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TTree.cxx,v 1.211 2004/10/14 10:17:03 brun Exp $ +// @(#)root/tree:$Name: $:$Id: TTree.cxx,v 1.212 2004/10/18 12:32:12 brun Exp $ // Author: Rene Brun 12/01/96 /************************************************************************* @@ -1347,7 +1347,7 @@ TBranch *TTree::Bronch(const char *name, const char *classname, void *add, Int_t TString inclass; int stlcont = TClassEdit::IsSTLCont(classname); - if (stlcont>=1 && stlcont<=2 ) { + if ( (stlcont>=1 && stlcont<=8) || (stlcont>=-8 && stlcont<=-1) ) { inclass = TClassEdit::ShortType(classname,1+2+4).c_str(); TClass *inklass = gROOT->GetClass(inclass.Data()); if (!inklass) { @@ -1391,7 +1391,8 @@ TBranch *TTree::Bronch(const char *name, const char *classname, void *add, Int_t } //====> //====> special case of vector<...> or list<...> - if(stlcont>=1 && stlcont<=2) { + TVirtualCollectionProxy *collProxy = cl->GetCollectionProxy(); + if( collProxy ) { // MSF: stlcont>=1 && stlcont<=2) { TVirtualCollectionProxy *collProxy = cl->GetCollectionProxy()->Generate(); // TSTLCont *tstl = new TSTLCont(classname,(void*)objadd); TBranchElement *branch = new TBranchElement(name,collProxy,bufsize,splitlevel); fBranches.Add(branch); diff --git a/utils/src/RStl.cxx b/utils/src/RStl.cxx index 4c717924d3f..932eba074d2 100644 --- a/utils/src/RStl.cxx +++ b/utils/src/RStl.cxx @@ -1,4 +1,4 @@ -// @(#)root/utils:$Name: $:$Id: RStl.cxx,v 1.7 2004/04/15 06:41:49 brun Exp $ +// @(#)root/utils:$Name: $:$Id: RStl.cxx,v 1.8 2004/07/15 23:08:23 rdm Exp $ // Author: Philippe Canal 27/08/2003 /************************************************************************* @@ -267,6 +267,10 @@ void ROOT::RStl::WriteStreamer(FILE *file, G__ClassInfo &stlcl) { fprintf(file, "} // close namespace ROOT\n\n"); fprintf(file, "// Register the streamer (a typedef is used to avoid problem with macro parameters\n"); + + //if ( 0 != ::getenv("MY_ROOT") && ::getenv("MY_ROOT")[0]>'1' ) { + // fprintf(file, "// Disabled due customized build:\n// "); + //} fprintf(file, "RootStlStreamer(%s,%s)\n", typedefName.c_str(), streamerName.c_str()); fprintf(file, "\n"); diff --git a/utils/src/rootcint.cxx b/utils/src/rootcint.cxx index 6c0b03fd839..ff0ab040284 100644 --- a/utils/src/rootcint.cxx +++ b/utils/src/rootcint.cxx @@ -1,4 +1,4 @@ -// @(#)root/utils:$Name: $:$Id: rootcint.cxx,v 1.189 2004/10/08 07:39:21 brun Exp $ +// @(#)root/utils:$Name: $:$Id: rootcint.cxx,v 1.190 2004/10/11 10:30:24 rdm Exp $ // Author: Fons Rademakers 13/07/96 /************************************************************************* @@ -293,6 +293,11 @@ char *StrDup(const char *str); char FunNames[10000] = { 0 }; +//const char* root_style() { +// static const char* s = ::getenv("MY_ROOT"); +// return s; +//} + // static int check = 0; //______________________________________________________________________________ void SetFun (const char *fname) @@ -1641,7 +1646,10 @@ int STLContainerStreamer(G__DataMemberInfo &m, int rwmode) case kMap: case kMultiMap: - fprintf(fp, " R__stl.insert(make_pair(R__t,R__t2));\n"); + fprintf(fp, " std::pair<const %s,",TemplateArg(m).Name()); + fprintf(fp, "%s> R__t3(R__t,R__t2);\n",TemplateArg(m,1).Name()); + fprintf(fp, " R__stl.insert(R__t3);\n"); + //fprintf(fp, " R__stl.insert(%s::value_type(R__t,R__t2));\n",stlType.c_str()); break; case kSet: case kMultiSet: @@ -1756,6 +1764,7 @@ int STLStringStreamer(G__DataMemberInfo &m, int rwmode) } //______________________________________________________________________________ +#ifdef OLDSTREAMER int STLBaseStreamer(G__BaseClassInfo &m, int rwmode) { // Create Streamer code for an STL base class. Returns 1 if base class @@ -1959,7 +1968,7 @@ int STLBaseStreamer(G__BaseClassInfo &m, int rwmode) } return 0; } - +#endif //______________________________________________________________________________ int PointerToPointer(G__DataMemberInfo &m) { @@ -2203,11 +2212,59 @@ void WriteClassInit(G__ClassInfo &cl) fprintf(fp, " instance.SetDeleteArray(&deleteArray_%s);\n",mappedname.c_str()); fprintf(fp, " instance.SetDestructor(&destruct_%s);\n",mappedname.c_str()); } - if (stl==1 || stl==-1) { + if (stl != 0 && ((stl>0 && stl<8) || (stl<0 && stl>-8)) ) { + int idx = classname.find("<"); + int STL_type = (idx!=(int)std::string::npos) ? TClassEdit::STLKind(classname.substr(0,idx).c_str()) : 0; + //if ( root_style() && root_style()[0]>'0' ) { + //fprintf(stdout,"// Executing rootcint in customized mode:%s class:%s STL:%d\n", + //root_style(), classname.c_str(), stl); + switch(STL_type) { + case TClassEdit::kVector: + case TClassEdit::kList: + case TClassEdit::kDeque: + //switch(root_style()[0]) { + // case '3': + // fprintf(fp, " // Streamer and proxy omitted for class: %s\n",classname.c_str()); + // break; + // case '2': + fprintf(fp, " instance.AdoptStreamer(TCollectionProxy::genClassStreamer<TCollectionProxy::Pushback<%s > >());\n",classname.c_str()); + // case '1': + fprintf(fp, " instance.AdoptCollectionProxy(TCollectionProxy::genProxy<TCollectionProxy::Pushback<%s > >());\n",classname.c_str()); + // break; + //} + break; + case TClassEdit::kMap: + case TClassEdit::kMultiMap: + //switch(root_style()[0]) { + // case '3': + // break; + // case '2': + fprintf(fp, " instance.AdoptStreamer(TCollectionProxy::genClassStreamer<TCollectionProxy::MapInsert<%s > >());\n",classname.c_str()); + // case '1': + fprintf(fp, " instance.AdoptCollectionProxy(TCollectionProxy::genProxy<TCollectionProxy::MapInsert<%s > >());\n",classname.c_str()); + // break; + //} + break; + case TClassEdit::kSet: + case TClassEdit::kMultiSet: + //switch(root_style()[0]) { + // case '3': + // break; + // case '2': + fprintf(fp, " instance.AdoptStreamer(TCollectionProxy::genClassStreamer<TCollectionProxy::Insert<%s > >());\n",classname.c_str()); + // case '1': + fprintf(fp, " instance.AdoptCollectionProxy(TCollectionProxy::genProxy<TCollectionProxy::Insert<%s > >());\n",classname.c_str()); + // break; + //} + break; + } + //} + } + else if (stl==1 || stl==-1) { if (TClassEdit::IsVectorBool(classname.c_str())) { - fprintf(fp, " instance.AdoptCollectionProxy(new ::ROOT::TBoolVectorProxy<%s >);\n",classname.c_str()); + fprintf(fp, " instance.AdoptCollectionProxy(new ::ROOT::TBoolVectorProxy<%s >);\n",classname.c_str()); } else { - fprintf(fp, " instance.AdoptCollectionProxy(new ::ROOT::TVectorProxy<%s >);\n",classname.c_str()); + fprintf(fp, " instance.AdoptCollectionProxy(new ::ROOT::TVectorProxy<%s >);\n",classname.c_str()); } } fprintf(fp, " return &instance;\n"); @@ -4315,8 +4372,9 @@ int main(int argc, char **argv) fprintf(fp, "#endif\n\n"); fprintf(fp, "#include \"RtypesImp.h\"\n\n"); fprintf(fp, "#include \"TVectorProxy.h\"\n\n"); + fprintf(fp, "#include \"TCollectionProxy.h\"\n\n"); #ifdef R__SOLARIS - fprintf(fp, "// Since CINT ignores the std namespace, we need to do so in this file.\n"); + fprintf(fp, "// Since CINT ignores the std namespace, we need to do so in this file.\n"); fprintf(fp, "namespace std {} using namespace std;\n\n"); #endif @@ -4597,7 +4655,7 @@ int main(int argc, char **argv) WriteClassCode(cl); } - RStl::inst().WriteStreamer(fp); + //RStl::inst().WriteStreamer(fp); //replaced by new Markus code RStl::inst().WriteClassInit(fp); fclose(fp); -- GitLab