/***************************************************************************** Copyright (c) 2023, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *****************************************************************************/ #pragma once /* A normally small vector, inspired by llvm::SmallVector */ #include "my_global.h" #include #include class small_vector_base { protected: typedef uint32_t Size_T; void *BeginX; Size_T Size= 0, Capacity; small_vector_base()= delete; small_vector_base(void *small, size_t small_size) : BeginX(small), Capacity(Size_T(small_size)) {} ATTRIBUTE_COLD void grow_by_1(void *small, size_t element_size); public: size_t size() const { return Size; } size_t capacity() const { return Capacity; } bool empty() const { return !Size; } void clear() { Size= 0; } protected: void set_size(size_t N) { Size= Size_T(N); } }; template class small_vector : public small_vector_base { /** The fixed storage allocation */ T small[N]; using small_vector_base::set_size; void grow_if_needed() { if (unlikely(size() >= capacity())) grow_by_1(small, sizeof *small); } public: small_vector() : small_vector_base(small, N) { TRASH_ALLOC(small, sizeof small); } ~small_vector() { if (small != begin()) my_free(begin()); MEM_MAKE_ADDRESSABLE(small, sizeof small); } using iterator= T *; using const_iterator= const T *; using reverse_iterator= std::reverse_iterator; using reference= T &; using const_reference= const T&; iterator begin() { return static_cast(BeginX); } const_iterator begin() const { return static_cast(BeginX); } iterator end() { return begin() + size(); } const_iterator end() const { return begin() + size(); } reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } reference operator[](size_t i) { assert(i < size()); return begin()[i]; } const_reference operator[](size_t i) const { return const_cast(*this)[i]; } void erase(const_iterator S, const_iterator E) { set_size(std::move(const_cast(E), end(), const_cast(S)) - begin()); } void emplace_back(T &&arg) { grow_if_needed(); ::new (end()) T(arg); set_size(size() + 1); } };