1    	// @(#)root/cont:$Id$
2    	// Author: Markus Frank  28/10/04. Philippe Canal 02/01/2007
3    	
4    	/*************************************************************************
5    	 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
6    	 * All rights reserved.                                                  *
7    	 *                                                                       *
8    	 * For the licensing terms see $ROOTSYS/LICENSE.                         *
9    	 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
10   	 *************************************************************************/
11   	
12   	#ifndef ROOT_TCollectionProxyInfo
13   	#define ROOT_TCollectionProxyInfo
14   	
15   	//////////////////////////////////////////////////////////////////////////
16   	//                                                                      //
17   	//  Small helper to gather the information neede to generate a          //
18   	//  Collection Proxy                                                    //
19   	//
20   	//////////////////////////////////////////////////////////////////////////
21   	
22   	#ifndef ROOT_TError
23   	#include "TError.h"
24   	#endif 
25   	#include <vector>
26   	
27   	#if defined(_WIN32)
28   	   #if _MSC_VER<1300
29   	      #define TYPENAME
30   	      #define R__VCXX6
31   	   #else
32   	      #define TYPENAME typename
33   	   #endif
34   	#else
35   	   #define TYPENAME typename
36   	#endif
37   	
38   	namespace ROOT {
39   	
40   	   class TCollectionProxyInfo {
41   	      // This class is a place holder for the information needed
42   	      // to create the proper Collection Proxy.
43   	      // This is similar to Reflex's CollFuncTable.
44   	
45   	   public:
46   	
47   	      // Same value as TVirtualCollectionProxy.
48   	      static const UInt_t fgIteratorArenaSize = 16; // greater than sizeof(void*) + sizeof(UInt_t)
49   	
50   	   /** @class template TCollectionProxyInfo::IteratorValue 
51   	    *
52   	    * Small helper to encapsulate whether to return the value
53   	    * pointed to by the iterator or its address.
54   	    *
55   	    **/
56   	
57   	      template <typename Cont_t, typename value> struct IteratorValue {
58   	         static void* get(typename Cont_t::iterator &iter) {
59   	            return (void*)&(*iter);
60   	         }
61   	      };
62   	
63   	      template <typename Cont_t, typename value_ptr> struct IteratorValue<Cont_t, value_ptr*> {
64   	         static void* get(typename Cont_t::iterator &iter) {
65   	            return (void*)(*iter);
66   	         }
67   	      };
68   	
69   	   /** @class template TCollectionProxyInfo::Iterators 
70   	    *
71   	    * Small helper to implement the function to create,access and destroy
72   	    * iterators.
73   	    *
74   	    **/
75   	
76   	      template <typename Cont_t, bool large = false> 
77   	      struct Iterators {
78   	         typedef Cont_t *PCont_t;
79   	         typedef typename Cont_t::iterator iterator;
80   	
81   	         static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
82   	            PCont_t c = PCont_t(coll);
83   	            new (*begin_arena) iterator(c->begin());
84   	            new (*end_arena) iterator(c->end());
85   	         }
86   	         static void* copy(void *dest_arena, const void *source_ptr) {
87   	            iterator *source = (iterator *)(source_ptr);
88   	            new (dest_arena) iterator(*source);
89   	            return dest_arena; 
90   	         }
91   	         static void* next(void *iter_loc, const void *end_loc) {
92   	            iterator *end = (iterator *)(end_loc);
93   	            iterator *iter = (iterator *)(iter_loc);
94   	            if (*iter != *end) {
95   	               void *result = IteratorValue<Cont_t, typename Cont_t::value_type>::get(*iter);
96   	               ++(*iter);
97   	               return result;
98   	            }
99   	            return 0;
100  	         }
101  	         static void destruct1(void *iter_ptr) {
102  	            iterator *start = (iterator *)(iter_ptr);
103  	            start->~iterator();
104  	         }
105  	         static void destruct2(void *begin_ptr, void *end_ptr) {
106  	            iterator *start = (iterator *)(begin_ptr);
107  	            iterator *end = (iterator *)(end_ptr);
108  	            start->~iterator();
109  	            end->~iterator();
110  	         }
111  	      };
112  	
113  	      // For Vector we take an extra short cut to avoid derefencing
114  	      // the iterator all the time and redefine the 'address' of the
115  	      // iterator as the iterator itself.  This requires special handling
116  	      // in the looper (see TStreamerInfoAction) but is much faster.
117  	      template <typename T> struct Iterators<std::vector<T>, false> {
118  	         typedef std::vector<T> Cont_t;
119  	         typedef Cont_t *PCont_t;
120  	         typedef typename Cont_t::iterator iterator;
121  	
122  	         static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
123  	            PCont_t c = PCont_t(coll);
124  	            if (c->empty()) {
125  	               *begin_arena = 0;
126  	               *end_arena = 0;
127  	               return;
128  	            }
129  	            *begin_arena = &(*c->begin());
130  	#ifdef R__VISUAL_CPLUSPLUS
131  	            *end_arena = &(*(c->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
132  	#else
133  	            // coverity[past_the_end] Safe on other platforms
134  	            *end_arena = &(*c->end());
135  	#endif
136  	         }
137  	         static void* copy(void *dest, const void *source) {
138  	            *(void**)dest = *(void**)(const_cast<void*>(source));
139  	            return dest; 
140  	         }
141  	         static void* next(void * /* iter_loc */, const void * /* end_loc */) {
142  	            // Should not be used.
143  	            R__ASSERT(0 && "Intentionally not implemented, do not use.");
144  	            return 0;
145  	         }
146  	         static void destruct1(void  * /* iter_ptr */) {
147  	            // Nothing to do
148  	         }
149  	         static void destruct2(void * /* begin_ptr */, void * /* end_ptr */) {
150  	            // Nothing to do
151  	         }
152  	      };
153  	
154  	      template <typename Cont_t> struct Iterators<Cont_t, /* large= */ true > {
155  	         typedef Cont_t *PCont_t;
156  	         typedef typename Cont_t::iterator iterator;
157  	
158  	         static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
159  	            PCont_t  c = PCont_t(coll);
160  	            *begin_arena = new iterator(c->begin());
161  	            *end_arena = new iterator(c->end());        
162  	         }
163  	         static void* copy(void * /*dest_arena*/, const void *source_ptr) {
164  	            iterator *source = (iterator *)(source_ptr);
165  	            void *iter = new iterator(*source);
166  	            return iter;
167  	         }
168  	         static void* next(void *iter_loc, const void *end_loc) {
169  	            iterator *end = (iterator *)(end_loc);
170  	            iterator *iter = (iterator *)(iter_loc);
171  	            if (*iter != *end) {
172  	               void *result = IteratorValue<Cont_t, typename Cont_t::value_type>::get(*iter);
173  	               ++(*iter);
174  	               return result;
175  	            }
176  	            return 0;
177  	         }
178  	         static void destruct1(void *begin_ptr) {
179  	            iterator *start = (iterator *)(begin_ptr);
180  	            delete start;
181  	         }
182  	         static void destruct2(void *begin_ptr, void *end_ptr) {
183  	            iterator *start = (iterator *)(begin_ptr);
184  	            iterator *end = (iterator *)(end_ptr);
185  	            delete start;
186  	            delete end;
187  	         }
188  	      };
189  	
190  	  /** @class TCollectionProxyInfo::Environ TCollectionProxyInfo.h TCollectionProxyInfo.h
191  	    *
192  	    * Small helper to save proxy environment in the event of
193  	    * recursive calls.
194  	    *
195  	    * @author  M.Frank
196  	    * @version 1.0
197  	    * @date    10/10/2004
198  	    */
199  	#ifndef __CINT__
200  	   struct EnvironBase {
201  	   private:
202  	      EnvironBase(const EnvironBase&); // Intentionally not implement, copy is not supported
203  	      EnvironBase &operator=(const EnvironBase&); // Intentionally not implement, copy is not supported
204  	   public:
205  	      EnvironBase() : fIdx(0), fSize(0), fObject(0), fStart(0), fTemp(0), fUseTemp(kFALSE), fRefCount(1), fSpace(0)
206  	      {
207  	      }
208  	      virtual ~EnvironBase() {}
209  	      size_t              fIdx;
210  	      size_t              fSize;
211  	      void*               fObject;
212  	      void*               fStart;
213  	      void*               fTemp;
214  	      Bool_t              fUseTemp;
215  	      int                 fRefCount;
216  	      size_t              fSpace;      
217  	   };
218  	   template <typename T> struct Environ : public EnvironBase {
219  	      typedef T           Iter_t;
220  	      Iter_t              fIterator;
221  	      T& iter() { return fIterator; }
222  	      static void        *Create() {
223  	         return new Environ();
224  	      }
225  	   };
226  	#else
227  	   struct EnvironBase;
228  	   template <typename T> struct Environ;
229  	#endif
230  	
231  	   template <class T, class Q> struct PairHolder {
232  	      T first;
233  	      Q second;
234  	      PairHolder() {}
235  	      PairHolder(const PairHolder& c) : first(c.first), second(c.second) {}
236  	      virtual ~PairHolder() {}
237  	   private:
238  	      PairHolder& operator=(const PairHolder&);  // not implemented
239  	   };
240  	
241  	   template <class T> struct Address {
242  	      virtual ~Address() {}
243  	      static void* address(T ref) {
244  	         return (void*)&ref;
245  	      }
246  	   };
247  	
248  	   /** @class TCollectionProxyInfo::Type TCollectionProxyInfo.h TCollectionProxyInfo.h
249  	    *
250  	    * Small helper to encapsulate basic data accesses for
251  	    * all STL continers.
252  	    *
253  	    * @author  M.Frank
254  	    * @version 1.0
255  	    * @date    10/10/2004
256  	    */
257  	   template <class T> struct Type
258  	      : public Address<TYPENAME T::const_reference>
259  	   {
260  	      typedef T                      Cont_t;
261  	      typedef typename T::iterator   Iter_t;
262  	      typedef typename T::value_type Value_t;
263  	      typedef Environ<Iter_t>        Env_t;
264  	      typedef Env_t                 *PEnv_t;
265  	      typedef Cont_t                *PCont_t;
266  	      typedef Value_t               *PValue_t;
267  	
268  	      virtual ~Type() {}
269  	
270  	      static inline PCont_t object(void* ptr)   {
271  	         return PCont_t(PEnv_t(ptr)->fObject);
272  	      }
273  	      static void* size(void* env)  {
274  	         PEnv_t  e = PEnv_t(env);
275  	         e->fSize   = PCont_t(e->fObject)->size();
276  	         return &e->fSize;
277  	      }
278  	      static void* clear(void* env)  {
279  	         object(env)->clear();
280  	         return 0;
281  	      }
282  	      static void* first(void* env)  {
283  	         PEnv_t  e = PEnv_t(env);
284  	         PCont_t c = PCont_t(e->fObject);
285  	#if 0
286  	         // Assume iterators do not need destruction
287  	         ::new(e->buff) Iter_t(c->begin());
288  	#endif
289  	         e->fIterator = c->begin();
290  	         e->fSize  = c->size();
291  	         if ( 0 == e->fSize ) return e->fStart = 0;
292  	         TYPENAME T::const_reference ref = *(e->iter());
293  	         return e->fStart = Type<T>::address(ref);
294  	      }
295  	      static void* next(void* env)  {
296  	         PEnv_t  e = PEnv_t(env);
297  	         PCont_t c = PCont_t(e->fObject);
298  	         for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
299  	         // TODO: Need to find something for going backwards....
300  	         if ( e->iter() == c->end() ) return 0;
301  	         TYPENAME T::const_reference ref = *(e->iter());
302  	         return Type<T>::address(ref);
303  	      }
304  	      static void* construct(void *what, size_t size)  {
305  	         PValue_t m = PValue_t(what);
306  	         for (size_t i=0; i<size; ++i, ++m)
307  	            ::new(m) Value_t();
308  	         return 0;
309  	      }
310  	      static void* collect(void *coll, void *array)  {
311  	         PCont_t  c = PCont_t(coll);
312  	         PValue_t m = PValue_t(array);
313  	         for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
314  	            ::new(m) Value_t(*i);
315  	         return 0;
316  	      }
317  	      static void destruct(void *what, size_t size)  {
318  	         PValue_t m = PValue_t(what);
319  	         for (size_t i=0; i < size; ++i, ++m )
320  	            m->~Value_t();
321  	      }
322  	
323  	      static const bool fgLargeIterator = sizeof(typename Cont_t::iterator) > fgIteratorArenaSize;
324  	      typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
325  	
326  	   };
327  	
328  	   /** @class TCollectionProxyInfo::Map TCollectionProxyInfo.h TCollectionProxyInfo.h
329  	    *
330  	    * Small helper to encapsulate all necessary data accesses for
331  	    * containers like vector, list, deque
332  	    *
333  	    * @author  M.Frank
334  	    * @version 1.0
335  	    * @date    10/10/2004
336  	    */
337  	   template <class T> struct Pushback : public Type<T> {
338  	      typedef T                      Cont_t;
339  	      typedef typename T::iterator   Iter_t;
340  	      typedef typename T::value_type Value_t;
341  	      typedef Environ<Iter_t>        Env_t;
342  	      typedef Env_t                 *PEnv_t;
343  	      typedef Cont_t                *PCont_t;
344  	      typedef Value_t               *PValue_t;
345  	      static void resize(void* obj, size_t n) {
346  	         PCont_t c = PCont_t(obj);
347  	         c->resize(n);
348  	      }
349  	      static void* feed(void *from, void *to, size_t size)  {
350  	         PCont_t  c = PCont_t(to);
351  	         PValue_t m = PValue_t(from);
352  	         for (size_t i=0; i<size; ++i, ++m)
353  	            c->push_back(*m);
354  	         return 0;
355  	      }
356  	      static int value_offset()  {
357  	         return 0;
358  	      }
359  	   };
360  	
361  	   /** @class TCollectionProxyInfo::Map TCollectionProxyInfo.h TCollectionProxyInfo.h
362  	    *
363  	    * Small helper to encapsulate all necessary data accesses for
364  	    * containers like set, multiset etc.
365  	    *
366  	    * @author  M.Frank
367  	    * @version 1.0
368  	    * @date    10/10/2004
369  	    */
370  	   template <class T> struct Insert : public Type<T> {
371  	      typedef T                      Cont_t;
372  	      typedef typename T::iterator   Iter_t;
373  	      typedef typename T::value_type Value_t;
374  	      typedef Environ<Iter_t>        Env_t;
375  	      typedef Env_t                 *PEnv_t;
376  	      typedef Cont_t                *PCont_t;
377  	      typedef Value_t               *PValue_t;
378  	      static void* feed(void *from, void *to, size_t size)  {
379  	         PCont_t  c = PCont_t(to);
380  	         PValue_t m = PValue_t(from);
381  	         for (size_t i=0; i<size; ++i, ++m)
382  	            c->insert(*m);
383  	         return 0;
384  	      }
385  	      static void resize(void* /* obj */, size_t )  {
386  	         ;
387  	      }
388  	      static int value_offset()  {
389  	         return 0;
390  	      }
391  	   };
392  	
393  	   /** @class TCollectionProxyInfo::Map TCollectionProxyInfo.h TCollectionProxyInfo.h
394  	    *
395  	    * Small helper to encapsulate all necessary data accesses for
396  	    * containers like set, multiset etc.
397  	    *
398  	    * @author  M.Frank
399  	    * @version 1.0
400  	    * @date    10/10/2004
401  	    */
402  	   template <class T> struct MapInsert : public Type<T> {
403  	      typedef T                      Cont_t;
404  	      typedef typename T::iterator   Iter_t;
405  	      typedef typename T::value_type Value_t;
406  	      typedef Environ<Iter_t>        Env_t;
407  	      typedef Env_t                 *PEnv_t;
408  	      typedef Cont_t                *PCont_t;
409  	      typedef Value_t               *PValue_t;
410  	      static void* feed(void *from, void *to, size_t size)  {
411  	         PCont_t  c = PCont_t(to);
412  	         PValue_t m = PValue_t(from);
413  	         for (size_t i=0; i<size; ++i, ++m)
414  	            c->insert(*m);
415  	         return 0;
416  	      }
417  	      static void resize(void* /* obj */, size_t )  {
418  	         ;
419  	      }
420  	      static int value_offset()  {
421  	         return ((char*)&((PValue_t(0x1000))->second)) - ((char*)PValue_t(0x1000));
422  	      }
423  	   };
424  	
425  	      
426  	   public:
427  	#ifndef __CINT__
428  	      const type_info &fInfo;
429  	#endif
430  	      size_t fIterSize;
431  	      size_t fValueDiff;
432  	      int    fValueOffset;
433  	      void*  (*fSizeFunc)(void*);
434  	      void   (*fResizeFunc)(void*,size_t);
435  	      void*  (*fClearFunc)(void*);
436  	      void*  (*fFirstFunc)(void*);
437  	      void*  (*fNextFunc)(void*);
438  	      void*  (*fConstructFunc)(void*,size_t);
439  	      void   (*fDestructFunc)(void*,size_t);
440  	      void*  (*fFeedFunc)(void*,void*,size_t);
441  	      void*  (*fCollectFunc)(void*,void*);
442  	      void*  (*fCreateEnv)();
443  	      
444  	      // Set of function of direct iteration of the collections.
445  	      void (*fCreateIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy);
446  	      // begin_arena and end_arena should contain the location of memory arena  of size fgIteratorSize. 
447  	      // If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
448  	      // Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
449  	      
450  	      void* (*fCopyIterator)(void *dest, const void *source);
451  	      // Copy the iterator source, into dest.   dest should contain should contain the location of memory arena  of size fgIteratorSize.
452  	      // If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
453  	      // Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
454  	      
455  	      void* (*fNext)(void *iter, const void *end);
456  	      // iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
457  	      // 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
458  	      // If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
459  	      // which case 'Next' will return the value of the pointer.
460  	      
461  	      void (*fDeleteSingleIterator)(void *iter);
462  	      void (*fDeleteTwoIterators)(void *begin, void *end);
463  	      // If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
464  	      // Otherwise just call the iterator's destructor.
465  	      
466  	   public:
467  	      TCollectionProxyInfo(const type_info& info,
468  	                           size_t iter_size,
469  	                           size_t value_diff,
470  	                           int    value_offset,
471  	                           void*  (*size_func)(void*),
472  	                           void   (*resize_func)(void*,size_t),
473  	                           void*  (*clear_func)(void*),
474  	                           void*  (*first_func)(void*),
475  	                           void*  (*next_func)(void*),
476  	                           void*  (*construct_func)(void*,size_t),
477  	                           void   (*destruct_func)(void*,size_t),
478  	                           void*  (*feed_func)(void*,void*,size_t),
479  	                           void*  (*collect_func)(void*,void*),
480  	                           void*  (*create_env)(),
481  	                           void   (*getIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy) = 0,
482  	                           void*  (*copyIterator)(void *dest, const void *source) = 0,
483  	                           void*  (*next)(void *iter, const void *end) = 0,
484  	                           void   (*deleteSingleIterator)(void *iter) = 0,
485  	                           void   (*deleteTwoIterators)(void *begin, void *end) = 0
486  	                           ) :
487  	         fInfo(info), fIterSize(iter_size), fValueDiff(value_diff),
488  	         fValueOffset(value_offset),
489  	         fSizeFunc(size_func),fResizeFunc(resize_func),fClearFunc(clear_func),
490  	         fFirstFunc(first_func),fNextFunc(next_func),fConstructFunc(construct_func),
491  	         fDestructFunc(destruct_func),fFeedFunc(feed_func),fCollectFunc(collect_func),
492  	         fCreateEnv(create_env),
493  	         fCreateIterators(getIterators),fCopyIterator(copyIterator),fNext(next),
494  	         fDeleteSingleIterator(deleteSingleIterator),fDeleteTwoIterators(deleteTwoIterators)
495  	      {
496  	      }
497  	 
498  	      /// Generate proxy from template
499  	      template <class T> static ROOT::TCollectionProxyInfo* Generate(const T&)  {
500  	         // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
501  	         // template (used to described the behavior of the stl collection.
502  	         // Typical use looks like:
503  	         //      ::ROOT::TCollectionProxyInfo::Generate(TCollectionProxyInfo::Pushback< vector<string> >()));
504  	         
505  	         PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
506  	            (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
507  	         return new ROOT::TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
508  	                                               sizeof(TYPENAME T::Iter_t),
509  	                                               (((char*)&p->second)-((char*)&p->first)),
510  	                                               T::value_offset(),
511  	                                               T::size,
512  	                                               T::resize,
513  	                                               T::clear,
514  	                                               T::first,
515  	                                               T::next,
516  	                                               T::construct,
517  	                                               T::destruct,
518  	                                               T::feed,
519  	                                               T::collect,
520  	                                               T::Env_t::Create,
521  	                                               T::Iterators_t::create,
522  	                                               T::Iterators_t::copy,
523  	                                               T::Iterators_t::next,
524  	                                               T::Iterators_t::destruct1,
525  	                                               T::Iterators_t::destruct2);
526  	      }
527  	
528  	      template <class T> static ROOT::TCollectionProxyInfo Get(const T&)  {
529  	
530  	         // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
531  	         // template (used to described the behavior of the stl collection.
532  	         // Typical use looks like:
533  	         //      ::ROOT::TCollectionProxyInfo::Get(TCollectionProxyInfo::Pushback< vector<string> >()));
534  	         
535  	         PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
536  	            (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
537  	         return ROOT::TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
538  	                                           sizeof(TYPENAME T::Iter_t),
539  	                                           (((char*)&p->second)-((char*)&p->first)),
540  	                                           T::value_offset(),
541  	                                           T::size,
542  	                                           T::resize,
543  	                                           T::clear,
544  	                                           T::first,
545  	                                           T::next,
546  	                                           T::construct,
547  	                                           T::destruct,
548  	                                           T::feed,
549  	                                           T::collect,
550  	                                           T::Env_t::Create);
551  	      }
552  	
553  	   };
554  	
555  	   template <> struct TCollectionProxyInfo::Type<std::vector<Bool_t> >
556  	   : public TCollectionProxyInfo::Address<std::vector<Bool_t>::const_reference>
557  	   {
558  	      typedef std::vector<Bool_t>             Cont_t;
559  	      typedef std::vector<Bool_t>::iterator   Iter_t;
560  	      typedef std::vector<Bool_t>::value_type Value_t;
561  	      typedef Environ<Iter_t>                 Env_t;
562  	      typedef Env_t                          *PEnv_t;
563  	      typedef Cont_t                         *PCont_t;
564  	      typedef Value_t                        *PValue_t;
565  	      
566  	      virtual ~Type() {}
567  	      
568  	      static inline PCont_t object(void* ptr)   {
569  	         return PCont_t(PEnv_t(ptr)->fObject);
570  	      }
571  	      static void* size(void* env)  {
572  	         PEnv_t  e = PEnv_t(env);
573  	         e->fSize   = PCont_t(e->fObject)->size();
574  	         return &e->fSize;
575  	      }
576  	      static void* clear(void* env)  {
577  	         object(env)->clear();
578  	         return 0;
579  	      }
580  	      static void* first(void* env)  {
581  	         PEnv_t  e = PEnv_t(env);
582  	         PCont_t c = PCont_t(e->fObject);
583  	#if 0
584  	         // Assume iterators do not need destruction
585  	         ::new(e->buff) Iter_t(c->begin());
586  	#endif
587  	         e->fIterator = c->begin();
588  	         e->fSize  = c->size();
589  	         return 0;
590  	      }
591  	      static void* next(void* env)  {
592  	         PEnv_t  e = PEnv_t(env);
593  	         PCont_t c = PCont_t(e->fObject);
594  	         for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
595  	         // TODO: Need to find something for going backwards....
596  	         return 0;
597  	      }
598  	      static void* construct(void*,size_t)  {
599  	         // Nothing to construct.
600  	         return 0;
601  	      }
602  	      static void* collect(void *coll, void *array)  {
603  	         PCont_t  c = PCont_t(coll);
604  	         PValue_t m = PValue_t(array); // 'start' is a buffer outside the container.
605  	         for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
606  	            ::new(m) Value_t(*i);
607  	         return 0;
608  	      }
609  	      static void destruct(void*,size_t)  {
610  	         // Nothing to destruct.
611  	      }
612  	
613  	      //static const bool fgLargeIterator = sizeof(Cont_t::iterator) > fgIteratorArenaSize;
614  	      //typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
615  	
616  	      struct Iterators {
617  	         typedef Cont_t *PCont_t;
618  	         typedef Cont_t::iterator iterator;
619  	
620  	         static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
621  	            PCont_t c = PCont_t(coll);
622  	            new (*begin_arena) iterator(c->begin());
623  	            new (*end_arena) iterator(c->end());
624  	         }
625  	         static void* copy(void *dest_arena, const void *source_ptr) {
626  	            const iterator *source = (const iterator *)(source_ptr);
627  	            new (dest_arena) iterator(*source);
628  	            return dest_arena;
629  	         }
630  	         static void* next(void *iter_loc, const void *end_loc) {
631  	            const iterator *end = (const iterator *)(end_loc);
632  	            iterator *iter = (iterator *)(iter_loc);
633  	            if (*iter != *end) {
634  	               ++(*iter);
635  	               //if (*iter != *end) {
636  	               //   return IteratorValue<Cont_t, Cont_t::value_type>::get(*iter);
637  	               //}
638  	            }
639  	            return 0;
640  	         }
641  	         static void destruct1(void *iter_ptr) {
642  	            iterator *start = (iterator *)(iter_ptr);
643  	            start->~iterator();
644  	         }
645  	         static void destruct2(void *begin_ptr, void *end_ptr) {
646  	            iterator *start = (iterator *)(begin_ptr);
647  	            iterator *end = (iterator *)(end_ptr);
648  	            start->~iterator();
649  	            end->~iterator();
650  	         }
651  	      };
652  	      typedef Iterators Iterators_t;
653  	
654  	   };
655  	   
656  	   template <> struct TCollectionProxyInfo::Pushback<std::vector<bool> > : public TCollectionProxyInfo::Type<std::vector<Bool_t> > {
657  	      typedef std::vector<Bool_t>    Cont_t;
658  	      typedef Cont_t::iterator       Iter_t;
659  	      typedef Cont_t::value_type     Value_t;
660  	      typedef Environ<Iter_t>        Env_t;
661  	      typedef Env_t                 *PEnv_t;
662  	      typedef Cont_t                *PCont_t;
663  	      typedef Value_t               *PValue_t;
664  	      
665  	      static void resize(void* obj,size_t n) {
666  	         PCont_t c = PCont_t(obj);
667  	         c->resize(n);
668  	      }
669  	      static void* feed(void* from, void *to, size_t size)  {
670  	         PCont_t  c = PCont_t(to);
671  	         PValue_t m = PValue_t(from);
672  	         for (size_t i=0; i<size; ++i, ++m)
673  	            c->push_back(*m);
674  	         return 0;
675  	      }
676  	      static int value_offset()  {
677  	         return 0;
678  	      }
679  	   };
680  	
681  	#ifndef __CINT__
682  	   // Need specialization for boolean references due to stupid STL vector<bool>
683  	   template<> inline void* ::ROOT::TCollectionProxyInfo::Address<std::vector<Bool_t>::const_reference>::address(std::vector<Bool_t>::const_reference ) {
684  	      R__ASSERT(0);
685  	      return 0;
686  	   }
687  	#endif
688  	   
689  	   template <typename T> class TStdBitsetHelper {
690  	      // This class is intentionally empty, this is scaffolding to allow the equivalent
691  	      // of 'template <int N> struct TCollectionProxyInfo::Type<std::bitset<N> >' which 
692  	      // is not effective in C++ (as of gcc 4.3.3).
693  	   };
694  	
695  	#ifndef __CINT__
696  	   template <typename Bitset_t> struct TCollectionProxyInfo::Type<ROOT::TStdBitsetHelper<Bitset_t> > : public TCollectionProxyInfo::Address<const Bool_t &>
697  	   {
698  	      typedef Bitset_t                 Cont_t;
699  	      typedef std::pair<size_t,Bool_t> Iter_t;
700  	      typedef Bool_t                   Value_t;
701  	      typedef Environ<Iter_t>          Env_t;
702  	      typedef Env_t                   *PEnv_t;
703  	      typedef Cont_t                  *PCont_t;
704  	      typedef Value_t                 *PValue_t;
705  	      
706  	      virtual ~Type() {}
707  	      
708  	      static inline PCont_t object(void* ptr)   {
709  	         return PCont_t(PEnv_t(ptr)->fObject);
710  	      }
711  	      static void* size(void* env)  {
712  	         PEnv_t  e = PEnv_t(env);
713  	         e->fSize   = PCont_t(e->fObject)->size();
714  	         return &e->fSize;
715  	      }
716  	      static void* clear(void* env)  {
717  	         object(env)->reset();
718  	         return 0;
719  	      }
720  	      static void* first(void* env)  {
721  	         PEnv_t  e = PEnv_t(env);
722  	         PCont_t c = PCont_t(e->fObject);
723  	         e->fIterator.first = 0;
724  	         e->fIterator.second = c->size() > 0 ? c->test(e->fIterator.first) : false ;  // Iterator actually hold the value.
725  	         e->fSize  = c->size();
726  	         return 0;
727  	      }
728  	      static void* next(void* env)  {
729  	         PEnv_t  e = PEnv_t(env);
730  	         PCont_t c = PCont_t(e->fObject);
731  	         for (; e->fIdx > 0 && e->fIterator.first != c->size(); ++(e->fIterator.first), --e->fIdx){ }
732  	         e->fIterator.second = (e->fIterator.first != c->size()) ? c->test(e->fIterator.first) : false;
733  	         return 0;
734  	      }
735  	      static void* construct(void*,size_t)  {
736  	         // Nothing to construct.
737  	         return 0;
738  	      }
739  	      static void* collect(void *coll, void *array)  {
740  	         PCont_t  c = PCont_t(coll);
741  	         PValue_t m = PValue_t(array); // 'start' is a buffer outside the container.
742  	         for (size_t i=0; i != c->size(); ++i, ++m )
743  	            *m = c->test(i);
744  	         return 0;
745  	      }
746  	      static void destruct(void*,size_t)  {
747  	         // Nothing to destruct.
748  	      }
749  	
750  	      //static const bool fgLargeIterator = sizeof(typename Cont_t::iterator) > fgIteratorArenaSize;
751  	      //typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
752  	
753  	      struct Iterators {
754  	         typedef Cont_t *PCont_t;
755  	         union PtrSize_t { size_t fIndex; void *fAddress; };
756  	         typedef std::pair<PtrSize_t,Bool_t> iterator;
757  	         // In the end iterator we store the bitset pointer
758  	         // and do not use the 'second' part of the pair.
759  	         // In the other iterator we store the index
760  	         // and the value.
761  	
762  	         static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
763  	            iterator *begin = new (*begin_arena) iterator;
764  	            begin->first.fIndex = 0;
765  	            begin->second = false;
766  	            iterator *end = new (*end_arena) iterator;
767  	            end->first.fAddress = coll;
768  	            end->second = false;
769  	         }
770  	         static void* copy(void *dest_arena, const void *source_ptr) {
771  	            const iterator *source = (const iterator *)(source_ptr);
772  	            new (dest_arena) iterator(*source);
773  	            return dest_arena;
774  	         }
775  	         static void* next(void *iter_loc, const void *end_loc) {
776  	            const iterator *end = (const iterator *)(end_loc);
777  	            PCont_t c = (PCont_t)end->first.fAddress;
778  	            iterator *iter = (iterator *)(iter_loc);
779  	            if (iter->first.fIndex != c->size()) {
780  	               iter->second = c->test(iter->first.fIndex);
781  	               ++(iter->first.fIndex);
782  	            }
783  	            return &(iter->second);
784  	         }
785  	         static void destruct1(void *iter_ptr) {
786  	            iterator *start = (iterator *)(iter_ptr);
787  	            start->~iterator();
788  	         }
789  	         static void destruct2(void *begin_ptr, void *end_ptr) {
790  	            iterator *start = (iterator *)(begin_ptr);
791  	            iterator *end = (iterator *)(end_ptr);
792  	            start->~iterator();
793  	            end->~iterator();
794  	         }
795  	      };
796  	      typedef Iterators Iterators_t;
797  	   };
798  	   
799  	   template <typename Bitset_t> 
800  	   struct TCollectionProxyInfo::Pushback<ROOT::TStdBitsetHelper<Bitset_t>  > : public TCollectionProxyInfo::Type<TStdBitsetHelper<Bitset_t> > {
801  	      typedef Bitset_t         Cont_t;
802  	      typedef bool             Iter_t;
803  	      typedef bool             Value_t;
804  	      typedef Environ<Iter_t>  Env_t;
805  	      typedef Env_t           *PEnv_t;
806  	      typedef Cont_t          *PCont_t;
807  	      typedef Value_t         *PValue_t;
808  	      
809  	      static void resize(void*,size_t)  {
810  	      }
811  	      static void* feed(void *from, void *to, size_t size)  {
812  	         PCont_t  c = PCont_t(to);
813  	         PValue_t m = PValue_t(from); 
814  	         for (size_t i=0; i<size; ++i, ++m)
815  	            c->set(i,*m);
816  	         return 0;
817  	      }
818  	      static int value_offset()  {
819  	         return 0;
820  	      }
821  	   };
822  	#endif
823  	   
824  	}
825  	
826  	#endif
827