15 #include <string_view>
18 #if defined(__clang__)
19 # pragma clang diagnostic push
20 # pragma clang diagnostic ignored "-Wuninitialized"
31 std::memcpy(heap, sb.heap, sb.
size());
36 if (sb.usingAllocatedBuffer) {
38 bufferCapacity = sb.bufferCapacity;
39 usingAllocatedBuffer = sb.usingAllocatedBuffer;
40 nonOwning = sb.nonOwning;
41 sb.usingAllocatedBuffer =
false;
43 std::memcpy(buffer.data(), sb.heap, sb.bufferSize);
46 bufferSize = sb.bufferSize;
47 sb.heap = sb.buffer.data();
48 sb.bufferCapacity = 64;
53 typename T = std::enable_if_t<std::is_constructible_v<std::string_view, U>>>
56 std::string_view val(std::forward<U>(u));
58 std::memcpy(heap, val.data(), val.size());
74 resize(
size, std::byte{val});
79 if (usingAllocatedBuffer && !nonOwning) {
89 std::memcpy(heap, sb.heap, sb.
size());
92 SmallBuffer& operator=(SmallBuffer&& sb) noexcept
94 if (usingAllocatedBuffer) {
96 if (sb.heap == heap) {
97 bufferSize = sb.bufferSize;
98 bufferCapacity = sb.bufferCapacity;
102 if (sb.heap == heap) {
103 bufferSize = sb.bufferSize;
109 if (sb.usingAllocatedBuffer) {
111 bufferCapacity = sb.bufferCapacity;
112 usingAllocatedBuffer =
true;
113 nonOwning = sb.nonOwning;
115 std::memcpy(buffer.data(), sb.heap, sb.bufferSize);
116 usingAllocatedBuffer =
false;
118 heap = buffer.data();
121 bufferSize = sb.bufferSize;
122 sb.heap = sb.buffer.data();
123 sb.bufferCapacity = 64;
125 sb.usingAllocatedBuffer =
false;
129 typename T = std::enable_if_t<std::is_constructible_v<std::string_view, U>>>
130 SmallBuffer& operator=(U&& u)
132 std::string_view val(std::forward<U>(u));
133 if (
reinterpret_cast<const std::byte*
>(val.data()) == heap) {
134 bufferSize = val.size();
138 if (val.size() > 0) {
139 std::memcpy(heap, val.data(), val.size());
144 std::byte*
data()
const {
return heap; }
148 std::byte*
end() {
return heap + bufferSize; }
150 const std::byte*
begin()
const {
return heap; }
152 const std::byte*
end()
const {
return heap + bufferSize; }
154 std::byte
operator[](
size_t index)
const {
return heap[index]; }
158 std::byte
at(
size_t index)
const
160 if (index >= bufferSize) {
161 throw(std::out_of_range(
"specified index is not valid"));
166 std::byte&
at(
size_t index)
168 if (index >= bufferSize) {
169 throw(std::out_of_range(
"specified index is not valid"));
178 std::invalid_argument(
"invalid range specified, end pointer before start pointer"));
180 const auto* st1 =
reinterpret_cast<const std::byte*
>(start);
181 const auto* end1 =
reinterpret_cast<const std::byte*
>(
end);
183 std::memcpy(heap, st1, end1 - st1);
185 void assign(
const void* start, std::size_t
size)
187 const auto* st1 =
reinterpret_cast<const std::byte*
>(start);
189 std::memcpy(heap, st1,
size);
191 void append(
const void* start,
const void*
end)
195 std::invalid_argument(
"invalid range specified, end pointer before start pointer"));
197 const auto* st1 =
reinterpret_cast<const std::byte*
>(start);
198 const auto* end1 =
reinterpret_cast<const std::byte*
>(
end);
199 auto csize = bufferSize;
200 resize(bufferSize + (end1 - st1));
201 std::memcpy(heap + csize, st1, end1 - st1);
203 void append(
const void* start, std::size_t
size)
205 const auto* st1 =
reinterpret_cast<const std::byte*
>(start);
206 auto csize = bufferSize;
207 resize(bufferSize +
size);
208 std::memcpy(heap + csize, st1,
size);
210 void append(std::string_view
data)
212 const auto* st1 =
reinterpret_cast<const std::byte*
>(
data.data());
213 auto csize = bufferSize;
214 resize(bufferSize +
data.size());
215 std::memcpy(heap + csize, st1,
data.size());
218 void push_back(
char c) { append(&c, 1); }
220 void pop_back() { bufferSize > 0 ? --bufferSize : 0; }
224 return std::string_view{
reinterpret_cast<const char*
>(heap), bufferSize};
230 if (bufferCapacity > bufferSize) {
231 heap[bufferSize] = std::byte(0);
238 const char*
char_data()
const {
return reinterpret_cast<const char*
>(heap); }
242 auto* newHeap =
reinterpret_cast<std::byte*
>(
data);
243 if (usingAllocatedBuffer && !nonOwning) {
244 if (newHeap != heap) {
252 usingAllocatedBuffer =
true;
257 auto* newHeap =
reinterpret_cast<std::byte*
>(
data);
258 if (usingAllocatedBuffer && !nonOwning) {
259 if (newHeap == heap) {
272 usingAllocatedBuffer =
true;
274 void resize(
size_t size)
279 void resize(
size_t size, std::byte val)
282 if (
size > bufferSize) {
283 std::memset(heap + bufferSize, std::to_integer<int>(val),
size - bufferSize);
287 void reserve(
size_t size)
289 static constexpr
size_t bigSize{
sizeof(size_t) == 8 ? 0x010
'0000'0000U : 0xFFFF
'0000U};
290 if (size > bufferCapacity) {
291 if (size > bigSize) {
292 throw(std::bad_alloc());
294 auto* ndata = new std::byte[size + 8];
295 std::memcpy(ndata, heap, bufferSize);
296 if (usingAllocatedBuffer && !nonOwning) {
301 usingAllocatedBuffer = true;
302 bufferCapacity = size + 8;
306 bool empty() const { return (bufferSize == 0); }
308 std::size_t size() const { return bufferSize; }
310 std::size_t capacity() const { return bufferCapacity; }
312 void clear() { bufferSize = 0; }
315 void swap(SmallBuffer& sb2) noexcept
317 if (sb2.usingAllocatedBuffer && usingAllocatedBuffer) {
318 std::swap(heap, sb2.heap);
319 std::swap(nonOwning, sb2.nonOwning);
320 std::swap(bufferCapacity, sb2.bufferCapacity);
321 std::swap(bufferSize, sb2.bufferSize);
322 } else if (usingAllocatedBuffer) {
324 sb2.bufferCapacity = bufferCapacity;
325 sb2.usingAllocatedBuffer = true;
326 sb2.nonOwning = nonOwning;
327 usingAllocatedBuffer = false;
329 heap = buffer.data();
332 std::memcpy(heap, sb2.buffer.data(), sb2.size());
333 std::swap(sb2.bufferSize, bufferSize);
334 } else if (sb2.usingAllocatedBuffer) {
336 bufferCapacity = sb2.bufferCapacity;
337 usingAllocatedBuffer = true;
338 nonOwning = sb2.nonOwning;
339 sb2.usingAllocatedBuffer = false;
340 sb2.nonOwning = false;
341 sb2.heap = buffer.data();
342 sb2.bufferCapacity = 64;
344 std::memcpy(sb2.heap, buffer.data(), bufferSize);
345 std::swap(sb2.bufferSize, bufferSize);
347 std::swap(sb2.buffer, buffer);
348 std::swap(sb2.bufferSize, bufferSize);
354 if (!usingAllocatedBuffer) {
357 auto* released = heap;
358 heap = buffer.data();
359 usingAllocatedBuffer = false;
367 std::array<std::byte, 64> buffer{{std::byte{0}}};
368 std::size_t bufferSize{0};
369 std::size_t bufferCapacity{64};
371 bool nonOwning{false};
372 bool usingAllocatedBuffer{false};
376 inline bool operator==(const SmallBuffer& sb1, const SmallBuffer& sb2)
378 return (sb1.to_string() == sb2.to_string());
382 inline bool operator!=(const SmallBuffer& sb1, const SmallBuffer& sb2)
384 return (sb1.to_string() != sb2.to_string());
387 #if defined(__clang__)
388 # pragma clang diagnostic pop
391 } // namespace helics