Mercurial > hg > sv-dependency-builds
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); |