comparison win64-msvc/include/kj/array.h @ 63:0f2d93caa50c

Update Win64 capnp builds to v0.6
author Chris Cannam
date Mon, 22 May 2017 18:56:49 +0100
parents d93140aac40b
children
comparison
equal deleted inserted replaced
62:0994c39f1e94 63:0f2d93caa50c
249 249
250 template <typename U> 250 template <typename U>
251 friend class Array; 251 friend class Array;
252 }; 252 };
253 253
254 static_assert(!canMemcpy<Array<char>>(), "canMemcpy<>() is broken");
255
254 namespace _ { // private 256 namespace _ { // private
255 257
256 class HeapArrayDisposer final: public ArrayDisposer { 258 class HeapArrayDisposer final: public ArrayDisposer {
257 public: 259 public:
258 template <typename T> 260 template <typename T>
292 template <typename T, typename Iterator> Array<T> heapArray(Iterator begin, Iterator end); 294 template <typename T, typename Iterator> Array<T> heapArray(Iterator begin, Iterator end);
293 template <typename T> Array<T> heapArray(std::initializer_list<T> init); 295 template <typename T> Array<T> heapArray(std::initializer_list<T> init);
294 // Allocate a heap array containing a copy of the given content. 296 // Allocate a heap array containing a copy of the given content.
295 297
296 template <typename T, typename Container> 298 template <typename T, typename Container>
297 Array<T> heapArrayFromIterable(Container&& a) { return heapArray(a.begin(), a.end()); } 299 Array<T> heapArrayFromIterable(Container&& a) { return heapArray<T>(a.begin(), a.end()); }
298 template <typename T> 300 template <typename T>
299 Array<T> heapArrayFromIterable(Array<T>&& a) { return mv(a); } 301 Array<T> heapArrayFromIterable(Array<T>&& a) { return mv(a); }
300 302
301 // ======================================================================================= 303 // =======================================================================================
302 // ArrayBuilder 304 // ArrayBuilder
374 return *pos++; 376 return *pos++;
375 } 377 }
376 378
377 template <typename Container> 379 template <typename Container>
378 void addAll(Container&& container) { 380 void addAll(Container&& container) {
379 addAll(container.begin(), container.end()); 381 addAll<decltype(container.begin()), !isReference<Container>()>(
380 } 382 container.begin(), container.end());
381 383 }
382 template <typename Iterator> 384
385 template <typename Iterator, bool move = false>
383 void addAll(Iterator start, Iterator end); 386 void addAll(Iterator start, Iterator end);
384 387
385 void removeLast() { 388 void removeLast() {
386 KJ_IREQUIRE(pos > ptr, "No elements present to remove."); 389 KJ_IREQUIRE(pos > ptr, "No elements present to remove.");
387 kj::dtor(*--pos); 390 kj::dtor(*--pos);
391 }
392
393 void truncate(size_t size) {
394 KJ_IREQUIRE(size <= this->size(), "can't use truncate() to expand");
395
396 T* target = ptr + size;
397 if (__has_trivial_destructor(T)) {
398 pos = target;
399 } else {
400 while (pos > target) {
401 kj::dtor(*--pos);
402 }
403 }
404 }
405
406 void resize(size_t size) {
407 KJ_IREQUIRE(size <= capacity(), "can't resize past capacity");
408
409 T* target = ptr + size;
410 if (target > pos) {
411 // expand
412 if (__has_trivial_constructor(T)) {
413 pos = target;
414 } else {
415 while (pos < target) {
416 kj::ctor(*pos++);
417 }
418 }
419 } else {
420 // truncate
421 if (__has_trivial_destructor(T)) {
422 pos = target;
423 } else {
424 while (pos > target) {
425 kj::dtor(*--pos);
426 }
427 }
428 }
388 } 429 }
389 430
390 Array<T> finish() { 431 Array<T> finish() {
391 // We could safely remove this check if we assume that the disposer implementation doesn't 432 // We could safely remove this check if we assume that the disposer implementation doesn't
392 // need to know the original capacity, as is thes case with HeapArrayDisposer since it uses 433 // need to know the original capacity, as is thes case with HeapArrayDisposer since it uses
499 540
500 // ======================================================================================= 541 // =======================================================================================
501 // KJ_MAP 542 // KJ_MAP
502 543
503 #define KJ_MAP(elementName, array) \ 544 #define KJ_MAP(elementName, array) \
504 ::kj::_::Mapper<KJ_DECLTYPE_REF(array)>(array) * [&](decltype(*(array).begin()) elementName) 545 ::kj::_::Mapper<KJ_DECLTYPE_REF(array)>(array) * \
546 [&](typename ::kj::_::Mapper<KJ_DECLTYPE_REF(array)>::Element elementName)
505 // Applies some function to every element of an array, returning an Array of the results, with 547 // Applies some function to every element of an array, returning an Array of the results, with
506 // nice syntax. Example: 548 // nice syntax. Example:
507 // 549 //
508 // StringPtr foo = "abcd"; 550 // StringPtr foo = "abcd";
509 // Array<char> bar = KJ_MAP(c, foo) -> char { return c + 1; }; 551 // Array<char> bar = KJ_MAP(c, foo) -> char { return c + 1; };
521 for (auto iter = array.begin(); iter != array.end(); ++iter) { 563 for (auto iter = array.begin(); iter != array.end(); ++iter) {
522 builder.add(func(*iter)); 564 builder.add(func(*iter));
523 } 565 }
524 return builder.finish(); 566 return builder.finish();
525 } 567 }
568 typedef decltype(*kj::instance<T>().begin()) Element;
569 };
570
571 template <typename T, size_t s>
572 struct Mapper<T(&)[s]> {
573 T* array;
574 Mapper(T* array): array(array) {}
575 template <typename Func>
576 auto operator*(Func&& func) -> Array<decltype(func(*array))> {
577 auto builder = heapArrayBuilder<decltype(func(*array))>(s);
578 for (size_t i = 0; i < s; i++) {
579 builder.add(func(array[i]));
580 }
581 return builder.finish();
582 }
583 typedef decltype(*array)& Element;
526 }; 584 };
527 585
528 } // namespace _ (private) 586 } // namespace _ (private)
529 587
530 // ======================================================================================= 588 // =======================================================================================
596 template <typename T> 654 template <typename T>
597 T* HeapArrayDisposer::allocateUninitialized(size_t count) { 655 T* HeapArrayDisposer::allocateUninitialized(size_t count) {
598 return Allocate_<T, true, true>::allocate(0, count); 656 return Allocate_<T, true, true>::allocate(0, count);
599 } 657 }
600 658
601 template <typename Element, typename Iterator, bool = canMemcpy<Element>()> 659 template <typename Element, typename Iterator, bool move, bool = canMemcpy<Element>()>
602 struct CopyConstructArray_; 660 struct CopyConstructArray_;
603 661
604 template <typename T> 662 template <typename T, bool move>
605 struct CopyConstructArray_<T, T*, true> { 663 struct CopyConstructArray_<T, T*, move, true> {
606 static inline T* apply(T* __restrict__ pos, T* start, T* end) { 664 static inline T* apply(T* __restrict__ pos, T* start, T* end) {
607 memcpy(pos, start, reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start)); 665 memcpy(pos, start, reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start));
608 return pos + (end - start); 666 return pos + (end - start);
609 } 667 }
610 }; 668 };
611 669
612 template <typename T> 670 template <typename T>
613 struct CopyConstructArray_<T, const T*, true> { 671 struct CopyConstructArray_<T, const T*, false, true> {
614 static inline T* apply(T* __restrict__ pos, const T* start, const T* end) { 672 static inline T* apply(T* __restrict__ pos, const T* start, const T* end) {
615 memcpy(pos, start, reinterpret_cast<const byte*>(end) - reinterpret_cast<const byte*>(start)); 673 memcpy(pos, start, reinterpret_cast<const byte*>(end) - reinterpret_cast<const byte*>(start));
616 return pos + (end - start); 674 return pos + (end - start);
617 } 675 }
618 }; 676 };
619 677
620 template <typename T, typename Iterator> 678 template <typename T, typename Iterator, bool move>
621 struct CopyConstructArray_<T, Iterator, true> { 679 struct CopyConstructArray_<T, Iterator, move, true> {
622 static inline T* apply(T* __restrict__ pos, Iterator start, Iterator end) { 680 static inline T* apply(T* __restrict__ pos, Iterator start, Iterator end) {
623 // Since both the copy constructor and assignment operator are trivial, we know that assignment 681 // Since both the copy constructor and assignment operator are trivial, we know that assignment
624 // is equivalent to copy-constructing. So we can make this case somewhat easier for the 682 // is equivalent to copy-constructing. So we can make this case somewhat easier for the
625 // compiler to optimize. 683 // compiler to optimize.
626 while (start != end) { 684 while (start != end) {
629 return pos; 687 return pos;
630 } 688 }
631 }; 689 };
632 690
633 template <typename T, typename Iterator> 691 template <typename T, typename Iterator>
634 struct CopyConstructArray_<T, Iterator, false> { 692 struct CopyConstructArray_<T, Iterator, false, false> {
635 struct ExceptionGuard { 693 struct ExceptionGuard {
636 T* start; 694 T* start;
637 T* pos; 695 T* pos;
638 inline explicit ExceptionGuard(T* pos): start(pos), pos(pos) {} 696 inline explicit ExceptionGuard(T* pos): start(pos), pos(pos) {}
639 ~ExceptionGuard() noexcept(false) { 697 ~ExceptionGuard() noexcept(false) {
664 } 722 }
665 } 723 }
666 }; 724 };
667 725
668 template <typename T, typename Iterator> 726 template <typename T, typename Iterator>
669 inline T* copyConstructArray(T* dst, Iterator start, Iterator end) { 727 struct CopyConstructArray_<T, Iterator, true, false> {
670 return CopyConstructArray_<T, Decay<Iterator>>::apply(dst, start, end); 728 // Actually move-construct.
671 } 729
730 struct ExceptionGuard {
731 T* start;
732 T* pos;
733 inline explicit ExceptionGuard(T* pos): start(pos), pos(pos) {}
734 ~ExceptionGuard() noexcept(false) {
735 while (pos > start) {
736 dtor(*--pos);
737 }
738 }
739 };
740
741 static T* apply(T* __restrict__ pos, Iterator start, Iterator end) {
742 // Verify that T can be *implicitly* constructed from the source values.
743 if (false) implicitCast<T>(kj::mv(*start));
744
745 if (noexcept(T(kj::mv(*start)))) {
746 while (start != end) {
747 ctor(*pos++, kj::mv(*start++));
748 }
749 return pos;
750 } else {
751 // Crap. This is complicated.
752 ExceptionGuard guard(pos);
753 while (start != end) {
754 ctor(*guard.pos, kj::mv(*start++));
755 ++guard.pos;
756 }
757 guard.start = guard.pos;
758 return guard.pos;
759 }
760 }
761 };
672 762
673 } // namespace _ (private) 763 } // namespace _ (private)
674 764
675 template <typename T> 765 template <typename T>
676 template <typename Iterator> 766 template <typename Iterator, bool move>
677 void ArrayBuilder<T>::addAll(Iterator start, Iterator end) { 767 void ArrayBuilder<T>::addAll(Iterator start, Iterator end) {
678 pos = _::copyConstructArray(pos, start, end); 768 pos = _::CopyConstructArray_<RemoveConst<T>, Decay<Iterator>, move>::apply(pos, start, end);
679 } 769 }
680 770
681 template <typename T> 771 template <typename T>
682 Array<T> heapArray(const T* content, size_t size) { 772 Array<T> heapArray(const T* content, size_t size) {
683 ArrayBuilder<T> builder = heapArrayBuilder<T>(size); 773 ArrayBuilder<T> builder = heapArrayBuilder<T>(size);