openMSX
SerializeBuffer.cc
Go to the documentation of this file.
1#include "SerializeBuffer.hh"
2#include <cstdlib>
3#include <utility>
4
5namespace openmsx {
6
7// class OutputBuffer
8
10 : buf(lastSize)
11 , end(buf.data())
12 , finish(buf.data() + lastSize)
13{
14 // We've allocated a buffer with an estimated initial size. This
15 // estimate is based on the largest intermediate size of the previously
16 // required buffers.
17 // For correctness this initial size doesn't matter (we could even not
18 // allocate any initial buffer at all). But it can make a difference in
19 // performance. If later we discover the buffer is too small, we have
20 // to reallocate (and thus make a copy). In profiling this reallocation
21 // step was noticeable.
22
23 // Slowly drop the estimated required size. This makes sure that when
24 // we've overestimated the size once, we don't forever keep this too
25 // high value. For performance an overestimation is less bad than an
26 // underestimation.
27 lastSize -= lastSize >> 7;
28}
29
30#ifdef __GNUC__
31template<size_t LEN> void OutputBuffer::insertN(const void* __restrict data)
32{
33 uint8_t* newEnd = end + LEN;
34 if (newEnd <= finish) [[likely]] {
35 memcpy(end, data, LEN);
36 end = newEnd;
37 } else {
38 insertGrow(data, LEN);
39 }
40}
41// Force template instantiation
42template void OutputBuffer::insertN<1>(const void* __restrict data);
43template void OutputBuffer::insertN<2>(const void* __restrict data);
44template void OutputBuffer::insertN<4>(const void* __restrict data);
45template void OutputBuffer::insertN<8>(const void* __restrict data);
46#endif
47
48void OutputBuffer::insertN(const void* __restrict data, size_t len)
49{
50 uint8_t* newEnd = end + len;
51 if (newEnd <= finish) [[likely]] {
52 memcpy(end, data, len);
53 end = newEnd;
54 } else {
55 insertGrow(data, len);
56 }
57}
58
60{
61 size = end - buf.data();
62
63 // Deallocate unused buffer space.
64 buf.resize(size);
65
66 end = finish = nullptr;
67 return std::move(buf);
68}
69
70void OutputBuffer::grow(size_t len)
71{
72 size_t oldSize = end - buf.data();
73 size_t newSize = std::max(oldSize + len, oldSize + oldSize / 2);
74 buf.resize(newSize);
75 end = buf.data() + oldSize;
76 finish = buf.data() + newSize;
77}
78
79uint8_t* OutputBuffer::allocateGrow(size_t len)
80{
81 grow(len);
82 auto* result = end;
83 end += len;
84 return result;
85}
86
87void OutputBuffer::insertGrow(const void* __restrict data, size_t len)
88{
89 uint8_t* pos = allocateGrow(len);
90 memcpy(pos, data, len);
91}
92
93
94
95// class InputBuffer
96
97InputBuffer::InputBuffer(const uint8_t* data, size_t size)
98 : buf(data)
99#ifndef NDEBUG
100 , finish(buf + size)
101#endif
102{
103 (void)size;
104}
105
106} // namespace openmsx
InputBuffer(const uint8_t *data, size_t size)
Construct new InputBuffer, typically the data and size parameters will come from a MemBuffer object.
This class manages the lifetime of a block of memory.
Definition MemBuffer.hh:29
void resize(size_t size)
Grow or shrink the memory block.
Definition MemBuffer.hh:111
const T * data() const
Returns pointer to the start of the memory buffer.
Definition MemBuffer.hh:81
void insertN(const void *data, size_t len)
OutputBuffer()
Create an empty output buffer.
MemBuffer< uint8_t > release(size_t &size)
Release ownership of the buffer.
This file implemented 3 utility functions:
Definition Autofire.cc:9
constexpr auto end(const zstring_view &x)