xref: /llvm-project/libc/src/__support/fixedvector.h (revision 508398021d094ecfe6cea937d619c77121990e0d)
1daa44a23SSiva Chandra Reddy //===-- A data structure for a fixed capacity data store --------*- C++ -*-===//
2daa44a23SSiva Chandra Reddy //
3daa44a23SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4daa44a23SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5daa44a23SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6daa44a23SSiva Chandra Reddy //
7daa44a23SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8daa44a23SSiva Chandra Reddy 
9270547f3SGuillaume Chatelet #ifndef LLVM_LIBC_SRC___SUPPORT_FIXEDVECTOR_H
10270547f3SGuillaume Chatelet #define LLVM_LIBC_SRC___SUPPORT_FIXEDVECTOR_H
11daa44a23SSiva Chandra Reddy 
12daa44a23SSiva Chandra Reddy #include "src/__support/CPP/array.h"
13ad97ee25SNick Desaulniers #include "src/__support/CPP/iterator.h"
14*50839802SAlexey Samsonov #include "src/__support/libc_assert.h"
155ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
16*50839802SAlexey Samsonov #include "src/string/memory_utils/inline_memset.h"
17ad97ee25SNick Desaulniers 
185ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
19daa44a23SSiva Chandra Reddy 
20daa44a23SSiva Chandra Reddy // A fixed size data store backed by an underlying cpp::array data structure. It
21daa44a23SSiva Chandra Reddy // supports vector like API but is not resizable like a vector.
22daa44a23SSiva Chandra Reddy template <typename T, size_t CAPACITY> class FixedVector {
23daa44a23SSiva Chandra Reddy   cpp::array<T, CAPACITY> store;
24daa44a23SSiva Chandra Reddy   size_t item_count = 0;
25daa44a23SSiva Chandra Reddy 
26daa44a23SSiva Chandra Reddy public:
27*50839802SAlexey Samsonov   LIBC_INLINE constexpr FixedVector() = default;
28daa44a23SSiva Chandra Reddy 
29649edb8eSPiJoules   using iterator = typename cpp::array<T, CAPACITY>::iterator;
30*50839802SAlexey Samsonov   LIBC_INLINE constexpr FixedVector(iterator begin, iterator end)
31*50839802SAlexey Samsonov       : store{}, item_count{} {
32*50839802SAlexey Samsonov     LIBC_ASSERT(begin + CAPACITY >= end);
33649edb8eSPiJoules     for (; begin != end; ++begin)
34649edb8eSPiJoules       push_back(*begin);
35649edb8eSPiJoules   }
36649edb8eSPiJoules 
37005758ebSPiJoules   using const_iterator = typename cpp::array<T, CAPACITY>::const_iterator;
38*50839802SAlexey Samsonov   LIBC_INLINE constexpr FixedVector(const_iterator begin, const_iterator end)
39005758ebSPiJoules       : store{}, item_count{} {
40*50839802SAlexey Samsonov     LIBC_ASSERT(begin + CAPACITY >= end);
41005758ebSPiJoules     for (; begin != end; ++begin)
42005758ebSPiJoules       push_back(*begin);
43005758ebSPiJoules   }
44005758ebSPiJoules 
45*50839802SAlexey Samsonov   LIBC_INLINE constexpr FixedVector(size_t count, const T &value)
46*50839802SAlexey Samsonov       : store{}, item_count{} {
47*50839802SAlexey Samsonov     LIBC_ASSERT(count <= CAPACITY);
48649edb8eSPiJoules     for (size_t i = 0; i < count; ++i)
49649edb8eSPiJoules       push_back(value);
50649edb8eSPiJoules   }
51649edb8eSPiJoules 
52*50839802SAlexey Samsonov   LIBC_INLINE constexpr bool push_back(const T &obj) {
53daa44a23SSiva Chandra Reddy     if (item_count == CAPACITY)
54daa44a23SSiva Chandra Reddy       return false;
55daa44a23SSiva Chandra Reddy     store[item_count] = obj;
56daa44a23SSiva Chandra Reddy     ++item_count;
57daa44a23SSiva Chandra Reddy     return true;
58daa44a23SSiva Chandra Reddy   }
59daa44a23SSiva Chandra Reddy 
60*50839802SAlexey Samsonov   LIBC_INLINE constexpr const T &back() const {
61*50839802SAlexey Samsonov     LIBC_ASSERT(!empty());
62*50839802SAlexey Samsonov     return store[item_count - 1];
63*50839802SAlexey Samsonov   }
64daa44a23SSiva Chandra Reddy 
65*50839802SAlexey Samsonov   LIBC_INLINE constexpr T &back() {
66*50839802SAlexey Samsonov     LIBC_ASSERT(!empty());
67*50839802SAlexey Samsonov     return store[item_count - 1];
68*50839802SAlexey Samsonov   }
69daa44a23SSiva Chandra Reddy 
70*50839802SAlexey Samsonov   LIBC_INLINE constexpr bool pop_back() {
71daa44a23SSiva Chandra Reddy     if (item_count == 0)
72daa44a23SSiva Chandra Reddy       return false;
73*50839802SAlexey Samsonov     inline_memset(&store[item_count - 1], 0, sizeof(T));
74daa44a23SSiva Chandra Reddy     --item_count;
75daa44a23SSiva Chandra Reddy     return true;
76daa44a23SSiva Chandra Reddy   }
77daa44a23SSiva Chandra Reddy 
78*50839802SAlexey Samsonov   LIBC_INLINE constexpr T &operator[](size_t idx) {
79*50839802SAlexey Samsonov     LIBC_ASSERT(idx < item_count);
80*50839802SAlexey Samsonov     return store[idx];
81*50839802SAlexey Samsonov   }
82649edb8eSPiJoules 
83*50839802SAlexey Samsonov   LIBC_INLINE constexpr const T &operator[](size_t idx) const {
84*50839802SAlexey Samsonov     LIBC_ASSERT(idx < item_count);
85*50839802SAlexey Samsonov     return store[idx];
86*50839802SAlexey Samsonov   }
87649edb8eSPiJoules 
88*50839802SAlexey Samsonov   LIBC_INLINE constexpr bool empty() const { return item_count == 0; }
89daa44a23SSiva Chandra Reddy 
90*50839802SAlexey Samsonov   LIBC_INLINE constexpr size_t size() const { return item_count; }
91649edb8eSPiJoules 
92daa44a23SSiva Chandra Reddy   // Empties the store for all practical purposes.
93*50839802SAlexey Samsonov   LIBC_INLINE constexpr void reset() {
94*50839802SAlexey Samsonov     inline_memset(store.data(), 0, sizeof(T) * item_count);
95*50839802SAlexey Samsonov     item_count = 0;
96*50839802SAlexey Samsonov   }
97daa44a23SSiva Chandra Reddy 
98daa44a23SSiva Chandra Reddy   // This static method does not free up the resources held by |store|,
99daa44a23SSiva Chandra Reddy   // say by calling `free` or something similar. It just does the equivalent
100daa44a23SSiva Chandra Reddy   // of the `reset` method. Considering that FixedVector is of fixed storage,
101daa44a23SSiva Chandra Reddy   // a `destroy` method like this should not be required. However, FixedVector
102daa44a23SSiva Chandra Reddy   // is used in a few places as an alternate for data structures which use
103daa44a23SSiva Chandra Reddy   // dynamically allocated storate. So, the `destroy` method like this
104daa44a23SSiva Chandra Reddy   // matches the `destroy` API of those other data structures so that users
105daa44a23SSiva Chandra Reddy   // can easily swap one data structure for the other.
106*50839802SAlexey Samsonov   LIBC_INLINE static void destroy(FixedVector<T, CAPACITY> *store) {
107*50839802SAlexey Samsonov     store->reset();
108*50839802SAlexey Samsonov   }
109ad97ee25SNick Desaulniers 
110ad97ee25SNick Desaulniers   using reverse_iterator = typename cpp::array<T, CAPACITY>::reverse_iterator;
111ad97ee25SNick Desaulniers   LIBC_INLINE constexpr reverse_iterator rbegin() {
112ad97ee25SNick Desaulniers     return reverse_iterator{&store[item_count]};
113ad97ee25SNick Desaulniers   }
114ad97ee25SNick Desaulniers   LIBC_INLINE constexpr reverse_iterator rend() { return store.rend(); }
115ce8bb9b5Sjameshu15869 
116ce8bb9b5Sjameshu15869   LIBC_INLINE constexpr iterator begin() { return store.begin(); }
117ce8bb9b5Sjameshu15869   LIBC_INLINE constexpr iterator end() { return iterator{&store[item_count]}; }
11854ca5a80SPiJoules 
11954ca5a80SPiJoules   LIBC_INLINE constexpr const_iterator begin() const { return store.begin(); }
12054ca5a80SPiJoules   LIBC_INLINE constexpr const_iterator end() const {
12154ca5a80SPiJoules     return const_iterator{&store[item_count]};
12254ca5a80SPiJoules   }
123daa44a23SSiva Chandra Reddy };
124daa44a23SSiva Chandra Reddy 
1255ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
126daa44a23SSiva Chandra Reddy 
127270547f3SGuillaume Chatelet #endif // LLVM_LIBC_SRC___SUPPORT_FIXEDVECTOR_H
128