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