00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef ABSL_CONTAINER_INLINED_VECTOR_H_
00036 #define ABSL_CONTAINER_INLINED_VECTOR_H_
00037
00038 #include <algorithm>
00039 #include <cassert>
00040 #include <cstddef>
00041 #include <cstdlib>
00042 #include <cstring>
00043 #include <initializer_list>
00044 #include <iterator>
00045 #include <memory>
00046 #include <type_traits>
00047 #include <utility>
00048
00049 #include "absl/algorithm/algorithm.h"
00050 #include "absl/base/internal/throw_delegate.h"
00051 #include "absl/base/optimization.h"
00052 #include "absl/base/port.h"
00053 #include "absl/container/internal/inlined_vector.h"
00054 #include "absl/memory/memory.h"
00055
00056 namespace absl {
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 template <typename T, size_t N, typename A = std::allocator<T>>
00068 class InlinedVector {
00069 static_assert(
00070 N > 0, "InlinedVector cannot be instantiated with `0` inlined elements.");
00071
00072 using Storage = inlined_vector_internal::Storage<T, N, A>;
00073 using AllocatorTraits = typename Storage::AllocatorTraits;
00074
00075 template <typename Iterator>
00076 using EnableIfAtLeastForwardIterator = absl::enable_if_t<
00077 inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>;
00078
00079 template <typename Iterator>
00080 using DisableIfAtLeastForwardIterator = absl::enable_if_t<
00081 !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>;
00082
00083 using rvalue_reference = typename Storage::rvalue_reference;
00084
00085 public:
00086 using allocator_type = typename Storage::allocator_type;
00087 using value_type = typename Storage::value_type;
00088 using pointer = typename Storage::pointer;
00089 using const_pointer = typename Storage::const_pointer;
00090 using reference = typename Storage::reference;
00091 using const_reference = typename Storage::const_reference;
00092 using size_type = typename Storage::size_type;
00093 using difference_type = typename Storage::difference_type;
00094 using iterator = typename Storage::iterator;
00095 using const_iterator = typename Storage::const_iterator;
00096 using reverse_iterator = typename Storage::reverse_iterator;
00097 using const_reverse_iterator = typename Storage::const_reverse_iterator;
00098
00099
00100
00101
00102
00103
00104 InlinedVector() noexcept(noexcept(allocator_type()))
00105 : storage_(allocator_type()) {}
00106
00107
00108 explicit InlinedVector(const allocator_type& alloc) noexcept
00109 : storage_(alloc) {}
00110
00111
00112 explicit InlinedVector(size_type n,
00113 const allocator_type& alloc = allocator_type())
00114 : storage_(alloc) {
00115 InitAssign(n);
00116 }
00117
00118
00119 InlinedVector(size_type n, const_reference v,
00120 const allocator_type& alloc = allocator_type())
00121 : storage_(alloc) {
00122 InitAssign(n, v);
00123 }
00124
00125
00126 InlinedVector(std::initializer_list<value_type> list,
00127 const allocator_type& alloc = allocator_type())
00128 : storage_(alloc) {
00129 AppendForwardRange(list.begin(), list.end());
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 template <typename ForwardIterator,
00139 EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
00140 InlinedVector(ForwardIterator first, ForwardIterator last,
00141 const allocator_type& alloc = allocator_type())
00142 : storage_(alloc) {
00143 AppendForwardRange(first, last);
00144 }
00145
00146
00147
00148 template <typename InputIterator,
00149 DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
00150 InlinedVector(InputIterator first, InputIterator last,
00151 const allocator_type& alloc = allocator_type())
00152 : storage_(alloc) {
00153 std::copy(first, last, std::back_inserter(*this));
00154 }
00155
00156
00157 InlinedVector(const InlinedVector& other)
00158 : InlinedVector(other, *other.storage_.GetAllocPtr()) {}
00159
00160
00161 InlinedVector(const InlinedVector& other, const allocator_type& alloc)
00162 : storage_(alloc) {
00163 reserve(other.size());
00164 if (storage_.GetIsAllocated()) {
00165 UninitializedCopy(other.begin(), other.end(),
00166 storage_.GetAllocatedData());
00167 storage_.SetAllocatedSize(other.size());
00168 } else {
00169 UninitializedCopy(other.begin(), other.end(), storage_.GetInlinedData());
00170 storage_.SetInlinedSize(other.size());
00171 }
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 InlinedVector(InlinedVector&& other) noexcept(
00190 absl::allocator_is_nothrow<allocator_type>::value ||
00191 std::is_nothrow_move_constructible<value_type>::value)
00192 : storage_(*other.storage_.GetAllocPtr()) {
00193 if (other.storage_.GetIsAllocated()) {
00194
00195
00196 storage_.SetAllocatedData(other.storage_.GetAllocatedData());
00197 storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
00198 storage_.SetAllocatedSize(other.size());
00199 other.storage_.SetInlinedSize(0);
00200 } else {
00201 UninitializedCopy(
00202 std::make_move_iterator(other.storage_.GetInlinedData()),
00203 std::make_move_iterator(other.storage_.GetInlinedData() +
00204 other.size()),
00205 storage_.GetInlinedData());
00206 storage_.SetInlinedSize(other.size());
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept(
00224 absl::allocator_is_nothrow<allocator_type>::value)
00225 : storage_(alloc) {
00226 if (other.storage_.GetIsAllocated()) {
00227 if (*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) {
00228
00229 storage_.SetAllocatedSize(other.size());
00230 storage_.SetAllocatedData(other.storage_.GetAllocatedData());
00231 storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
00232 other.storage_.SetInlinedSize(0);
00233 } else {
00234
00235 reserve(other.size());
00236 UninitializedCopy(std::make_move_iterator(other.begin()),
00237 std::make_move_iterator(other.end()),
00238 storage_.GetAllocatedData());
00239 storage_.SetAllocatedSize(other.size());
00240 }
00241 } else {
00242 UninitializedCopy(
00243 std::make_move_iterator(other.storage_.GetInlinedData()),
00244 std::make_move_iterator(other.storage_.GetInlinedData() +
00245 other.size()),
00246 storage_.GetInlinedData());
00247 storage_.SetInlinedSize(other.size());
00248 }
00249 }
00250
00251 ~InlinedVector() { clear(); }
00252
00253
00254
00255
00256
00257
00258
00259
00260 bool empty() const noexcept { return !size(); }
00261
00262
00263
00264
00265 size_type size() const noexcept { return storage_.GetSize(); }
00266
00267
00268
00269
00270 size_type max_size() const noexcept {
00271
00272
00273
00274 return (std::numeric_limits<size_type>::max)() / 2;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 size_type capacity() const noexcept {
00287 return storage_.GetIsAllocated() ? storage_.GetAllocatedCapacity()
00288 : static_cast<size_type>(N);
00289 }
00290
00291
00292
00293
00294
00295
00296 pointer data() noexcept {
00297 return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
00298 : storage_.GetInlinedData();
00299 }
00300
00301
00302
00303
00304 const_pointer data() const noexcept {
00305 return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
00306 : storage_.GetInlinedData();
00307 }
00308
00309
00310
00311
00312
00313 reference operator[](size_type i) {
00314 assert(i < size());
00315 return data()[i];
00316 }
00317
00318
00319
00320 const_reference operator[](size_type i) const {
00321 assert(i < size());
00322 return data()[i];
00323 }
00324
00325
00326
00327
00328 reference at(size_type i) {
00329 if (ABSL_PREDICT_FALSE(i >= size())) {
00330 base_internal::ThrowStdOutOfRange(
00331 "`InlinedVector::at(size_type)` failed bounds check");
00332 }
00333 return data()[i];
00334 }
00335
00336
00337
00338 const_reference at(size_type i) const {
00339 if (ABSL_PREDICT_FALSE(i >= size())) {
00340 base_internal::ThrowStdOutOfRange(
00341 "`InlinedVector::at(size_type) const` failed bounds check");
00342 }
00343 return data()[i];
00344 }
00345
00346
00347
00348
00349 reference front() {
00350 assert(!empty());
00351 return at(0);
00352 }
00353
00354
00355
00356 const_reference front() const {
00357 assert(!empty());
00358 return at(0);
00359 }
00360
00361
00362
00363
00364 reference back() {
00365 assert(!empty());
00366 return at(size() - 1);
00367 }
00368
00369
00370
00371 const_reference back() const {
00372 assert(!empty());
00373 return at(size() - 1);
00374 }
00375
00376
00377
00378
00379 iterator begin() noexcept { return data(); }
00380
00381
00382
00383 const_iterator begin() const noexcept { return data(); }
00384
00385
00386
00387
00388 iterator end() noexcept { return data() + size(); }
00389
00390
00391
00392 const_iterator end() const noexcept { return data() + size(); }
00393
00394
00395
00396
00397 const_iterator cbegin() const noexcept { return begin(); }
00398
00399
00400
00401
00402 const_iterator cend() const noexcept { return end(); }
00403
00404
00405
00406
00407 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
00408
00409
00410
00411 const_reverse_iterator rbegin() const noexcept {
00412 return const_reverse_iterator(end());
00413 }
00414
00415
00416
00417
00418 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
00419
00420
00421
00422 const_reverse_iterator rend() const noexcept {
00423 return const_reverse_iterator(begin());
00424 }
00425
00426
00427
00428
00429 const_reverse_iterator crbegin() const noexcept { return rbegin(); }
00430
00431
00432
00433
00434
00435 const_reverse_iterator crend() const noexcept { return rend(); }
00436
00437
00438
00439
00440 allocator_type get_allocator() const { return *storage_.GetAllocPtr(); }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 InlinedVector& operator=(std::initializer_list<value_type> list) {
00451 assign(list.begin(), list.end());
00452 return *this;
00453 }
00454
00455
00456
00457 InlinedVector& operator=(const InlinedVector& other) {
00458 if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
00459 const_pointer other_data = other.data();
00460 assign(other_data, other_data + other.size());
00461 }
00462 return *this;
00463 }
00464
00465
00466
00467
00468
00469
00470 InlinedVector& operator=(InlinedVector&& other) {
00471 if (ABSL_PREDICT_FALSE(this == std::addressof(other))) return *this;
00472
00473 if (other.storage_.GetIsAllocated()) {
00474 clear();
00475 storage_.SetAllocatedSize(other.size());
00476 storage_.SetAllocatedData(other.storage_.GetAllocatedData());
00477 storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
00478 other.storage_.SetInlinedSize(0);
00479 } else {
00480 if (storage_.GetIsAllocated()) clear();
00481
00482 if (size() < other.size()) {
00483 auto mid = std::make_move_iterator(other.begin() + size());
00484 std::copy(std::make_move_iterator(other.begin()), mid, begin());
00485 UninitializedCopy(mid, std::make_move_iterator(other.end()), end());
00486 } else {
00487 auto new_end = std::copy(std::make_move_iterator(other.begin()),
00488 std::make_move_iterator(other.end()), begin());
00489 Destroy(new_end, end());
00490 }
00491 storage_.SetInlinedSize(other.size());
00492 }
00493 return *this;
00494 }
00495
00496
00497
00498
00499 void assign(size_type n, const_reference v) {
00500 if (n <= size()) {
00501 std::fill_n(begin(), n, v);
00502 erase(begin() + n, end());
00503 return;
00504 }
00505
00506 reserve(n);
00507 std::fill_n(begin(), size(), v);
00508 if (storage_.GetIsAllocated()) {
00509 UninitializedFill(storage_.GetAllocatedData() + size(),
00510 storage_.GetAllocatedData() + n, v);
00511 storage_.SetAllocatedSize(n);
00512 } else {
00513 UninitializedFill(storage_.GetInlinedData() + size(),
00514 storage_.GetInlinedData() + n, v);
00515 storage_.SetInlinedSize(n);
00516 }
00517 }
00518
00519
00520
00521
00522 void assign(std::initializer_list<value_type> list) {
00523 assign(list.begin(), list.end());
00524 }
00525
00526
00527
00528 template <typename ForwardIterator,
00529 EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
00530 void assign(ForwardIterator first, ForwardIterator last) {
00531 auto length = std::distance(first, last);
00532
00533
00534 if (static_cast<size_type>(length) <= size()) {
00535 erase(std::copy(first, last, begin()), end());
00536 return;
00537 }
00538
00539 reserve(length);
00540 iterator out = begin();
00541 for (; out != end(); ++first, ++out) *out = *first;
00542 if (storage_.GetIsAllocated()) {
00543 UninitializedCopy(first, last, out);
00544 storage_.SetAllocatedSize(length);
00545 } else {
00546 UninitializedCopy(first, last, out);
00547 storage_.SetInlinedSize(length);
00548 }
00549 }
00550
00551
00552
00553 template <typename InputIterator,
00554 DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
00555 void assign(InputIterator first, InputIterator last) {
00556 size_type assign_index = 0;
00557 for (; (assign_index < size()) && (first != last);
00558 static_cast<void>(++assign_index), static_cast<void>(++first)) {
00559 *(data() + assign_index) = *first;
00560 }
00561 erase(data() + assign_index, data() + size());
00562 std::copy(first, last, std::back_inserter(*this));
00563 }
00564
00565
00566
00567
00568
00569
00570 void resize(size_type n) {
00571 size_type s = size();
00572 if (n < s) {
00573 erase(begin() + n, end());
00574 return;
00575 }
00576 reserve(n);
00577 assert(capacity() >= n);
00578
00579
00580 if (storage_.GetIsAllocated()) {
00581 UninitializedFill(storage_.GetAllocatedData() + s,
00582 storage_.GetAllocatedData() + n);
00583 storage_.SetAllocatedSize(n);
00584 } else {
00585 UninitializedFill(storage_.GetInlinedData() + s,
00586 storage_.GetInlinedData() + n);
00587 storage_.SetInlinedSize(n);
00588 }
00589 }
00590
00591
00592
00593
00594 void resize(size_type n, const_reference v) {
00595 size_type s = size();
00596 if (n < s) {
00597 erase(begin() + n, end());
00598 return;
00599 }
00600 reserve(n);
00601 assert(capacity() >= n);
00602
00603
00604 if (storage_.GetIsAllocated()) {
00605 UninitializedFill(storage_.GetAllocatedData() + s,
00606 storage_.GetAllocatedData() + n, v);
00607 storage_.SetAllocatedSize(n);
00608 } else {
00609 UninitializedFill(storage_.GetInlinedData() + s,
00610 storage_.GetInlinedData() + n, v);
00611 storage_.SetInlinedSize(n);
00612 }
00613 }
00614
00615
00616
00617
00618
00619 iterator insert(const_iterator pos, const_reference v) {
00620 return emplace(pos, v);
00621 }
00622
00623
00624
00625 iterator insert(const_iterator pos, rvalue_reference v) {
00626 return emplace(pos, std::move(v));
00627 }
00628
00629
00630
00631
00632 iterator insert(const_iterator pos, size_type n, const_reference v) {
00633 return InsertWithCount(pos, n, v);
00634 }
00635
00636
00637
00638
00639 iterator insert(const_iterator pos, std::initializer_list<value_type> list) {
00640 return insert(pos, list.begin(), list.end());
00641 }
00642
00643
00644
00645
00646
00647
00648
00649 template <typename ForwardIterator,
00650 EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
00651 iterator insert(const_iterator pos, ForwardIterator first,
00652 ForwardIterator last) {
00653 return InsertWithForwardRange(pos, first, last);
00654 }
00655
00656
00657
00658
00659 template <typename InputIterator,
00660 DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
00661 iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
00662 size_type initial_insert_index = std::distance(cbegin(), pos);
00663 for (size_type insert_index = initial_insert_index; first != last;
00664 static_cast<void>(++insert_index), static_cast<void>(++first)) {
00665 insert(data() + insert_index, *first);
00666 }
00667 return iterator(data() + initial_insert_index);
00668 }
00669
00670
00671
00672
00673
00674 template <typename... Args>
00675 iterator emplace(const_iterator pos, Args&&... args) {
00676 assert(pos >= begin());
00677 assert(pos <= end());
00678 if (ABSL_PREDICT_FALSE(pos == end())) {
00679 emplace_back(std::forward<Args>(args)...);
00680 return end() - 1;
00681 }
00682
00683 T new_t = T(std::forward<Args>(args)...);
00684
00685 auto range = ShiftRight(pos, 1);
00686 if (range.first == range.second) {
00687
00688 Construct(range.first, std::move(new_t));
00689 } else {
00690
00691 *range.first = T(std::move(new_t));
00692 }
00693
00694 return range.first;
00695 }
00696
00697
00698
00699
00700
00701 template <typename... Args>
00702 reference emplace_back(Args&&... args) {
00703 size_type s = size();
00704 if (ABSL_PREDICT_FALSE(s == capacity())) {
00705 return GrowAndEmplaceBack(std::forward<Args>(args)...);
00706 }
00707 pointer space;
00708 if (storage_.GetIsAllocated()) {
00709 storage_.SetAllocatedSize(s + 1);
00710 space = storage_.GetAllocatedData();
00711 } else {
00712 storage_.SetInlinedSize(s + 1);
00713 space = storage_.GetInlinedData();
00714 }
00715 return Construct(space + s, std::forward<Args>(args)...);
00716 }
00717
00718
00719
00720
00721 void push_back(const_reference v) { static_cast<void>(emplace_back(v)); }
00722
00723
00724
00725 void push_back(rvalue_reference v) {
00726 static_cast<void>(emplace_back(std::move(v)));
00727 }
00728
00729
00730
00731
00732
00733 void pop_back() noexcept {
00734 assert(!empty());
00735 size_type s = size();
00736 if (storage_.GetIsAllocated()) {
00737 Destroy(storage_.GetAllocatedData() + s - 1,
00738 storage_.GetAllocatedData() + s);
00739 storage_.SetAllocatedSize(s - 1);
00740 } else {
00741 Destroy(storage_.GetInlinedData() + s - 1, storage_.GetInlinedData() + s);
00742 storage_.SetInlinedSize(s - 1);
00743 }
00744 }
00745
00746
00747
00748
00749
00750
00751
00752 iterator erase(const_iterator pos) {
00753 assert(pos >= begin());
00754 assert(pos < end());
00755
00756 iterator position = const_cast<iterator>(pos);
00757 std::move(position + 1, end(), position);
00758 pop_back();
00759 return position;
00760 }
00761
00762
00763
00764
00765
00766 iterator erase(const_iterator from, const_iterator to) {
00767 assert(begin() <= from);
00768 assert(from <= to);
00769 assert(to <= end());
00770
00771 iterator range_start = const_cast<iterator>(from);
00772 iterator range_end = const_cast<iterator>(to);
00773
00774 size_type s = size();
00775 ptrdiff_t erase_gap = std::distance(range_start, range_end);
00776 if (erase_gap > 0) {
00777 pointer space;
00778 if (storage_.GetIsAllocated()) {
00779 space = storage_.GetAllocatedData();
00780 storage_.SetAllocatedSize(s - erase_gap);
00781 } else {
00782 space = storage_.GetInlinedData();
00783 storage_.SetInlinedSize(s - erase_gap);
00784 }
00785 std::move(range_end, space + s, range_start);
00786 Destroy(space + s - erase_gap, space + s);
00787 }
00788 return range_start;
00789 }
00790
00791
00792
00793
00794
00795 void clear() noexcept {
00796 const bool is_allocated = storage_.GetIsAllocated();
00797 pointer the_data =
00798 is_allocated ? storage_.GetAllocatedData() : storage_.GetInlinedData();
00799 inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), the_data,
00800 storage_.GetSize());
00801 storage_.SetInlinedSize(0);
00802 if (is_allocated) {
00803 AllocatorTraits::deallocate(*storage_.GetAllocPtr(), the_data,
00804 storage_.GetAllocatedCapacity());
00805 }
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 void reserve(size_type n) {
00818 if (n > capacity()) {
00819
00820 EnlargeBy(n - size());
00821 }
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 void shrink_to_fit() {
00836 const auto s = size();
00837 if (ABSL_PREDICT_FALSE(!storage_.GetIsAllocated() || s == capacity()))
00838 return;
00839
00840 if (s <= N) {
00841
00842
00843
00844 auto temp = std::move(*this);
00845 assign(std::make_move_iterator(temp.begin()),
00846 std::make_move_iterator(temp.end()));
00847 return;
00848 }
00849
00850
00851
00852
00853 pointer new_data = AllocatorTraits::allocate(*storage_.GetAllocPtr(), s);
00854 UninitializedCopy(std::make_move_iterator(storage_.GetAllocatedData()),
00855 std::make_move_iterator(storage_.GetAllocatedData() + s),
00856 new_data);
00857 ResetAllocation(new_data, s, s);
00858 }
00859
00860
00861
00862
00863 void swap(InlinedVector& other) {
00864 if (ABSL_PREDICT_FALSE(this == std::addressof(other))) return;
00865
00866 SwapImpl(other);
00867 }
00868
00869 private:
00870 template <typename H, typename TheT, size_t TheN, typename TheA>
00871 friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
00872
00873 void ResetAllocation(pointer new_data, size_type new_capacity,
00874 size_type new_size) {
00875 if (storage_.GetIsAllocated()) {
00876 Destroy(storage_.GetAllocatedData(),
00877 storage_.GetAllocatedData() + size());
00878 assert(begin() == storage_.GetAllocatedData());
00879 AllocatorTraits::deallocate(*storage_.GetAllocPtr(),
00880 storage_.GetAllocatedData(),
00881 storage_.GetAllocatedCapacity());
00882 } else {
00883 Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + size());
00884 }
00885
00886 storage_.SetAllocatedData(new_data);
00887 storage_.SetAllocatedCapacity(new_capacity);
00888 storage_.SetAllocatedSize(new_size);
00889 }
00890
00891 template <typename... Args>
00892 reference Construct(pointer p, Args&&... args) {
00893 std::allocator_traits<allocator_type>::construct(
00894 *storage_.GetAllocPtr(), p, std::forward<Args>(args)...);
00895 return *p;
00896 }
00897
00898 template <typename Iterator>
00899 void UninitializedCopy(Iterator src, Iterator src_last, pointer dst) {
00900 for (; src != src_last; ++dst, ++src) Construct(dst, *src);
00901 }
00902
00903 template <typename... Args>
00904 void UninitializedFill(pointer dst, pointer dst_last, const Args&... args) {
00905 for (; dst != dst_last; ++dst) Construct(dst, args...);
00906 }
00907
00908
00909 void Destroy(pointer from, pointer to) {
00910 for (pointer cur = from; cur != to; ++cur) {
00911 std::allocator_traits<allocator_type>::destroy(*storage_.GetAllocPtr(),
00912 cur);
00913 }
00914 #if !defined(NDEBUG)
00915
00916
00917
00918 if (from != to) {
00919 auto len = sizeof(value_type) * std::distance(from, to);
00920 std::memset(reinterpret_cast<void*>(from), 0xab, len);
00921 }
00922 #endif // !defined(NDEBUG)
00923 }
00924
00925
00926
00927
00928 void EnlargeBy(size_type delta) {
00929 const size_type s = size();
00930 assert(s <= capacity());
00931
00932 size_type target = (std::max)(static_cast<size_type>(N), s + delta);
00933
00934
00935
00936 size_type new_capacity = capacity();
00937 while (new_capacity < target) {
00938 new_capacity <<= 1;
00939 }
00940
00941 pointer new_data =
00942 AllocatorTraits::allocate(*storage_.GetAllocPtr(), new_capacity);
00943
00944 UninitializedCopy(std::make_move_iterator(data()),
00945 std::make_move_iterator(data() + s), new_data);
00946
00947 ResetAllocation(new_data, new_capacity, s);
00948 }
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 std::pair<iterator, iterator> ShiftRight(const_iterator position,
00959 size_type n) {
00960 iterator start_used = const_cast<iterator>(position);
00961 iterator start_raw = const_cast<iterator>(position);
00962 size_type s = size();
00963 size_type required_size = s + n;
00964
00965 if (required_size > capacity()) {
00966
00967 size_type new_capacity = capacity();
00968 while (new_capacity < required_size) {
00969 new_capacity <<= 1;
00970 }
00971
00972
00973 pointer new_data =
00974 AllocatorTraits::allocate(*storage_.GetAllocPtr(), new_capacity);
00975 size_type index = position - begin();
00976 UninitializedCopy(std::make_move_iterator(data()),
00977 std::make_move_iterator(data() + index), new_data);
00978 UninitializedCopy(std::make_move_iterator(data() + index),
00979 std::make_move_iterator(data() + s),
00980 new_data + index + n);
00981 ResetAllocation(new_data, new_capacity, s);
00982
00983
00984
00985 start_raw = begin() + index;
00986 start_used = start_raw;
00987 } else {
00988
00989
00990
00991 iterator pos = const_cast<iterator>(position);
00992 iterator raw_space = end();
00993 size_type slots_in_used_space = raw_space - pos;
00994 size_type new_elements_in_used_space = (std::min)(n, slots_in_used_space);
00995 size_type new_elements_in_raw_space = n - new_elements_in_used_space;
00996 size_type old_elements_in_used_space =
00997 slots_in_used_space - new_elements_in_used_space;
00998
00999 UninitializedCopy(
01000 std::make_move_iterator(pos + old_elements_in_used_space),
01001 std::make_move_iterator(raw_space),
01002 raw_space + new_elements_in_raw_space);
01003 std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
01004
01005
01006
01007
01008
01009 start_used = pos;
01010 start_raw = pos + new_elements_in_used_space;
01011 }
01012 storage_.AddSize(n);
01013 return std::make_pair(start_used, start_raw);
01014 }
01015
01016 template <typename... Args>
01017 reference GrowAndEmplaceBack(Args&&... args) {
01018 assert(size() == capacity());
01019 const size_type s = size();
01020
01021 size_type new_capacity = 2 * capacity();
01022 pointer new_data =
01023 AllocatorTraits::allocate(*storage_.GetAllocPtr(), new_capacity);
01024
01025 reference new_element =
01026 Construct(new_data + s, std::forward<Args>(args)...);
01027 UninitializedCopy(std::make_move_iterator(data()),
01028 std::make_move_iterator(data() + s), new_data);
01029
01030 ResetAllocation(new_data, new_capacity, s + 1);
01031
01032 return new_element;
01033 }
01034
01035 void InitAssign(size_type n) {
01036 if (n > static_cast<size_type>(N)) {
01037 pointer new_data = AllocatorTraits::allocate(*storage_.GetAllocPtr(), n);
01038 storage_.SetAllocatedData(new_data);
01039 storage_.SetAllocatedCapacity(n);
01040 UninitializedFill(storage_.GetAllocatedData(),
01041 storage_.GetAllocatedData() + n);
01042 storage_.SetAllocatedSize(n);
01043 } else {
01044 UninitializedFill(storage_.GetInlinedData(),
01045 storage_.GetInlinedData() + n);
01046 storage_.SetInlinedSize(n);
01047 }
01048 }
01049
01050 void InitAssign(size_type n, const_reference v) {
01051 if (n > static_cast<size_type>(N)) {
01052 pointer new_data = AllocatorTraits::allocate(*storage_.GetAllocPtr(), n);
01053 storage_.SetAllocatedData(new_data);
01054 storage_.SetAllocatedCapacity(n);
01055 UninitializedFill(storage_.GetAllocatedData(),
01056 storage_.GetAllocatedData() + n, v);
01057 storage_.SetAllocatedSize(n);
01058 } else {
01059 UninitializedFill(storage_.GetInlinedData(),
01060 storage_.GetInlinedData() + n, v);
01061 storage_.SetInlinedSize(n);
01062 }
01063 }
01064
01065 template <typename ForwardIt>
01066 void AppendForwardRange(ForwardIt first, ForwardIt last) {
01067 static_assert(absl::inlined_vector_internal::IsAtLeastForwardIterator<
01068 ForwardIt>::value,
01069 "");
01070
01071 auto length = std::distance(first, last);
01072 reserve(size() + length);
01073 if (storage_.GetIsAllocated()) {
01074 UninitializedCopy(first, last, storage_.GetAllocatedData() + size());
01075 storage_.SetAllocatedSize(size() + length);
01076 } else {
01077 UninitializedCopy(first, last, storage_.GetInlinedData() + size());
01078 storage_.SetInlinedSize(size() + length);
01079 }
01080 }
01081
01082 iterator InsertWithCount(const_iterator position, size_type n,
01083 const_reference v) {
01084 assert(position >= begin() && position <= end());
01085 if (ABSL_PREDICT_FALSE(n == 0)) return const_cast<iterator>(position);
01086
01087 value_type copy = v;
01088 std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
01089 std::fill(it_pair.first, it_pair.second, copy);
01090 UninitializedFill(it_pair.second, it_pair.first + n, copy);
01091
01092 return it_pair.first;
01093 }
01094
01095 template <typename ForwardIt>
01096 iterator InsertWithForwardRange(const_iterator position, ForwardIt first,
01097 ForwardIt last) {
01098 static_assert(absl::inlined_vector_internal::IsAtLeastForwardIterator<
01099 ForwardIt>::value,
01100 "");
01101 assert(position >= begin() && position <= end());
01102
01103 if (ABSL_PREDICT_FALSE(first == last))
01104 return const_cast<iterator>(position);
01105
01106 auto n = std::distance(first, last);
01107 std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
01108 size_type used_spots = it_pair.second - it_pair.first;
01109 auto open_spot = std::next(first, used_spots);
01110 std::copy(first, open_spot, it_pair.first);
01111 UninitializedCopy(open_spot, last, it_pair.second);
01112 return it_pair.first;
01113 }
01114
01115 void SwapImpl(InlinedVector& other) {
01116 using std::swap;
01117
01118 bool is_allocated = storage_.GetIsAllocated();
01119 bool other_is_allocated = other.storage_.GetIsAllocated();
01120
01121 if (is_allocated && other_is_allocated) {
01122
01123 storage_.SwapSizeAndIsAllocated(std::addressof(other.storage_));
01124 storage_.SwapAllocatedSizeAndCapacity(std::addressof(other.storage_));
01125 swap(*storage_.GetAllocPtr(), *other.storage_.GetAllocPtr());
01126
01127 return;
01128 }
01129
01130 if (!is_allocated && !other_is_allocated) {
01131
01132 InlinedVector* a = this;
01133 InlinedVector* b = std::addressof(other);
01134 if (size() < other.size()) {
01135 swap(a, b);
01136 }
01137
01138 const size_type a_size = a->size();
01139 const size_type b_size = b->size();
01140 assert(a_size >= b_size);
01141
01142 std::swap_ranges(a->storage_.GetInlinedData(),
01143 a->storage_.GetInlinedData() + b_size,
01144 b->storage_.GetInlinedData());
01145
01146
01147
01148 b->UninitializedCopy(a->storage_.GetInlinedData() + b_size,
01149 a->storage_.GetInlinedData() + a_size,
01150 b->storage_.GetInlinedData() + b_size);
01151 a->Destroy(a->storage_.GetInlinedData() + b_size,
01152 a->storage_.GetInlinedData() + a_size);
01153
01154 storage_.SwapSizeAndIsAllocated(std::addressof(other.storage_));
01155 swap(*storage_.GetAllocPtr(), *other.storage_.GetAllocPtr());
01156
01157 assert(b->size() == a_size);
01158 assert(a->size() == b_size);
01159 return;
01160 }
01161
01162
01163
01164
01165
01166
01167 InlinedVector* a = this;
01168 InlinedVector* b = std::addressof(other);
01169 if (a->storage_.GetIsAllocated()) {
01170 swap(a, b);
01171 }
01172
01173 assert(!a->storage_.GetIsAllocated());
01174 assert(b->storage_.GetIsAllocated());
01175
01176 const size_type a_size = a->size();
01177 const size_type b_size = b->size();
01178
01179 static_cast<void>(b_size);
01180
01181
01182 a->storage_.SwapSizeAndIsAllocated(std::addressof(b->storage_));
01183
01184
01185 pointer b_data = b->storage_.GetAllocatedData();
01186 size_type b_capacity = b->storage_.GetAllocatedCapacity();
01187
01188 b->UninitializedCopy(a->storage_.GetInlinedData(),
01189 a->storage_.GetInlinedData() + a_size,
01190 b->storage_.GetInlinedData());
01191 a->Destroy(a->storage_.GetInlinedData(),
01192 a->storage_.GetInlinedData() + a_size);
01193
01194 a->storage_.SetAllocatedData(b_data);
01195 a->storage_.SetAllocatedCapacity(b_capacity);
01196
01197 if (*a->storage_.GetAllocPtr() != *b->storage_.GetAllocPtr()) {
01198 swap(*a->storage_.GetAllocPtr(), *b->storage_.GetAllocPtr());
01199 }
01200
01201 assert(b->size() == a_size);
01202 assert(a->size() == b_size);
01203 }
01204
01205 Storage storage_;
01206 };
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 template <typename T, size_t N, typename A>
01217 void swap(absl::InlinedVector<T, N, A>& a,
01218 absl::InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {
01219 a.swap(b);
01220 }
01221
01222
01223
01224
01225 template <typename T, size_t N, typename A>
01226 bool operator==(const absl::InlinedVector<T, N, A>& a,
01227 const absl::InlinedVector<T, N, A>& b) {
01228 auto a_data = a.data();
01229 auto a_size = a.size();
01230 auto b_data = b.data();
01231 auto b_size = b.size();
01232 return absl::equal(a_data, a_data + a_size, b_data, b_data + b_size);
01233 }
01234
01235
01236
01237
01238 template <typename T, size_t N, typename A>
01239 bool operator!=(const absl::InlinedVector<T, N, A>& a,
01240 const absl::InlinedVector<T, N, A>& b) {
01241 return !(a == b);
01242 }
01243
01244
01245
01246
01247
01248 template <typename T, size_t N, typename A>
01249 bool operator<(const absl::InlinedVector<T, N, A>& a,
01250 const absl::InlinedVector<T, N, A>& b) {
01251 auto a_data = a.data();
01252 auto a_size = a.size();
01253 auto b_data = b.data();
01254 auto b_size = b.size();
01255 return std::lexicographical_compare(a_data, a_data + a_size, b_data,
01256 b_data + b_size);
01257 }
01258
01259
01260
01261
01262
01263 template <typename T, size_t N, typename A>
01264 bool operator>(const absl::InlinedVector<T, N, A>& a,
01265 const absl::InlinedVector<T, N, A>& b) {
01266 return b < a;
01267 }
01268
01269
01270
01271
01272
01273 template <typename T, size_t N, typename A>
01274 bool operator<=(const absl::InlinedVector<T, N, A>& a,
01275 const absl::InlinedVector<T, N, A>& b) {
01276 return !(b < a);
01277 }
01278
01279
01280
01281
01282
01283 template <typename T, size_t N, typename A>
01284 bool operator>=(const absl::InlinedVector<T, N, A>& a,
01285 const absl::InlinedVector<T, N, A>& b) {
01286 return !(a < b);
01287 }
01288
01289
01290
01291
01292
01293 template <typename H, typename TheT, size_t TheN, typename TheA>
01294 H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a) {
01295 auto a_data = a.data();
01296 auto a_size = a.size();
01297 return H::combine(H::combine_contiguous(std::move(h), a_data, a_size),
01298 a_size);
01299 }
01300
01301 }
01302
01303 #endif // ABSL_CONTAINER_INLINED_VECTOR_H_