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