aco/util: add small_vec
Signed-off-by: Rhys Perry <pendingchaos02@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27984>
This commit is contained in:
@@ -1031,6 +1031,153 @@ using bitfield_array64 = bitfield_array<T, offset, size, uint64_t>;
|
||||
|
||||
using bitarray8 = bitfield_array<uint8_t, 0, 8, uint8_t>;
|
||||
|
||||
/*
|
||||
* Resizable array optimized for small lengths. If it's smaller than Size, the elements will be
|
||||
* inlined into the object.
|
||||
*/
|
||||
template <typename T, uint32_t Size> class small_vec {
|
||||
public:
|
||||
static_assert(std::is_trivially_copyable<T>::value);
|
||||
static_assert(std::is_trivially_destructible<T>::value);
|
||||
|
||||
using value_type = T;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using size_type = uint16_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
constexpr small_vec() = default;
|
||||
constexpr small_vec(const small_vec&) = delete;
|
||||
|
||||
~small_vec()
|
||||
{
|
||||
if (capacity > Size)
|
||||
free(data);
|
||||
}
|
||||
|
||||
constexpr small_vec& operator=(const small_vec&) = delete;
|
||||
|
||||
constexpr iterator begin() noexcept { return capacity > Size ? data : inline_data; }
|
||||
|
||||
constexpr const_iterator begin() const noexcept { return capacity > Size ? data : inline_data; }
|
||||
|
||||
constexpr iterator end() noexcept { return std::next(begin(), length); }
|
||||
|
||||
constexpr const_iterator end() const noexcept { return std::next(begin(), length); }
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept { return begin(); }
|
||||
|
||||
constexpr const_iterator cend() const noexcept { return std::next(begin(), length); }
|
||||
|
||||
constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
|
||||
constexpr const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
|
||||
constexpr const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(cend());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(cbegin());
|
||||
}
|
||||
|
||||
constexpr reference operator[](const size_type index) noexcept
|
||||
{
|
||||
assert(length > index);
|
||||
return *(std::next(begin(), index));
|
||||
}
|
||||
|
||||
constexpr const_reference operator[](const size_type index) const noexcept
|
||||
{
|
||||
assert(length > index);
|
||||
return *(std::next(begin(), index));
|
||||
}
|
||||
|
||||
constexpr reference back() noexcept
|
||||
{
|
||||
assert(length > 0);
|
||||
return *(std::next(begin(), length - 1));
|
||||
}
|
||||
|
||||
constexpr const_reference back() const noexcept
|
||||
{
|
||||
assert(length > 0);
|
||||
return *(std::next(begin(), length - 1));
|
||||
}
|
||||
|
||||
constexpr reference front() noexcept
|
||||
{
|
||||
assert(length > 0);
|
||||
return *begin();
|
||||
}
|
||||
|
||||
constexpr const_reference front() const noexcept
|
||||
{
|
||||
assert(length > 0);
|
||||
return *cbegin();
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept { return length == 0; }
|
||||
|
||||
constexpr size_type size() const noexcept { return length; }
|
||||
|
||||
constexpr void pop_back() noexcept
|
||||
{
|
||||
assert(length > 0);
|
||||
--length;
|
||||
}
|
||||
|
||||
template <typename... Args> constexpr void emplace_back(Args... args) noexcept
|
||||
{
|
||||
if (length == capacity) {
|
||||
if (capacity > Size) {
|
||||
capacity *= 2;
|
||||
data = (T*)realloc(data, sizeof(T) * capacity);
|
||||
} else {
|
||||
capacity *= 2;
|
||||
T* ptr = (T*)malloc(sizeof(T) * capacity);
|
||||
memcpy(ptr, inline_data, sizeof(T) * length);
|
||||
data = ptr;
|
||||
}
|
||||
}
|
||||
*std::next(begin(), length++) = T(args...);
|
||||
}
|
||||
|
||||
constexpr void clear() noexcept
|
||||
{
|
||||
if (capacity > Size)
|
||||
free(data);
|
||||
length = 0;
|
||||
capacity = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t length = 0;
|
||||
uint32_t capacity = Size;
|
||||
union {
|
||||
T* data = NULL;
|
||||
T inline_data[Size];
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace aco
|
||||
|
||||
#endif // ACO_UTIL_H
|
||||
|
||||
Reference in New Issue
Block a user