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