openMSX
small_buffer.hh
Go to the documentation of this file.
1#ifndef SMALL_BUFFER_HH
2#define SMALL_BUFFER_HH
3
4#include "ranges.hh"
5#include "stl.hh"
6
7#include <algorithm>
8#include <array>
9#include <cassert>
10#include <iterator>
11#include <memory>
12#include <span>
13#include <type_traits>
14
15// A run-time-sized buffer of (possibly) uninitialized data.
16// Sizes upto 'BUF_SIZE' are stored internally in this object. Larger sizes use
17// heap-allocation. In other words: this implements the small-buffer-optimization.
18
19// Typically objects of this type are used as local variables. Not as member
20// variables of a larger class.
21
22// If you're sure the run-time will _always_ be <= BUF_SIZE, then it may be
23// better to use 'inplace_uninitialized_buffer'.
24
25template<typename T, size_t BUF_SIZE>
27{
28 static_assert(std::is_trivially_constructible_v<T>);
29
30public:
31 explicit small_buffer(uninitialized_tag, size_t size)
32 {
33 if (size <= BUF_SIZE) {
34 sp = std::span<T>(inplaceBuf.data(), size);
35 } else {
36 extBuf = std::make_unique_for_overwrite<T[]>(size);
37 sp = std::span<T>(extBuf.get(), size);
38 }
39 }
40
41 explicit small_buffer(size_t size, const T& t)
43 {
44 ranges::fill(sp, t);
45 }
46
47 template<typename Range>
48 explicit small_buffer(const Range& range)
49 : small_buffer(uninitialized_tag{}, std::distance(std::begin(range), std::end(range)))
50 {
51 std::copy(std::begin(range), std::end(range), begin());
52 }
53
54 [[nodiscard]] explicit(false) operator std::span<T>() noexcept { return sp; }
55
56 [[nodiscard]] auto size() const noexcept { return sp.size(); }
57 [[nodiscard]] auto empty() const noexcept { return sp.empty(); }
58 [[nodiscard]] auto data() noexcept { return sp.data(); }
59 [[nodiscard]] auto begin() noexcept { return sp.begin(); }
60 [[nodiscard]] auto end() noexcept { return sp.end(); }
61
62 [[nodiscard]] T& operator[](size_t index) {
63 assert(index < size());
64 return sp[index];
65 }
66 [[nodiscard]] T& front() {
67 assert(!empty());
68 return sp.front();
69 }
70 [[nodiscard]] T& back() {
71 assert(!empty());
72 return sp.back();
73 }
74
75private:
76 std::span<T> sp; // span representing the active buffer
77 std::array<T, BUF_SIZE> inplaceBuf;
78 std::unique_ptr<T[]> extBuf;
79};
80
81#endif
TclObject t
small_buffer(uninitialized_tag, size_t size)
small_buffer(size_t size, const T &t)
small_buffer(const Range &range)
constexpr void fill(ForwardRange &&range, const T &value)
Definition ranges.hh:315
STL namespace.
size_t size(std::string_view utf8)
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)