Skip to content

Commit 519ea2c

Browse files
committed
inplace memory buffer used for serialization
1 parent f1f79a4 commit 519ea2c

File tree

4 files changed

+111
-39
lines changed

4 files changed

+111
-39
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef guard_memoryInplaceBuffer_h_w9a8erft7gzkl
2+
#define guard_memoryInplaceBuffer_h_w9a8erft7gzkl
3+
4+
#include <cage-core/core.h>
5+
6+
namespace cage
7+
{
8+
template<uintPtr Capacity_ = 128>
9+
struct InplaceBuffer : private Immovable
10+
{
11+
static constexpr uintPtr Capacity = Capacity_;
12+
char data[Capacity];
13+
uintPtr size = 0;
14+
15+
CAGE_FORCE_INLINE operator PointerRange<char>() { return { data, data + size }; }
16+
CAGE_FORCE_INLINE operator PointerRange<const char>() const { return { data, data + size }; }
17+
};
18+
}
19+
20+
#endif // guard_memoryInplaceBuffer_h_w9a8erft7gzkl

sources/include/cage-core/serialization.h

+37-10
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,58 @@
11
#ifndef guard_serialization_h_edsg45df4h654fdr56h4gfd564h
22
#define guard_serialization_h_edsg45df4h654fdr56h4gfd564h
33

4-
#include <cage-core/core.h>
4+
#include <cage-core/memoryInplaceBuffer.h>
55

66
namespace cage
77
{
88
struct MemoryBuffer;
99

10+
namespace privat
11+
{
12+
struct CAGE_CORE_API SerializationInterface
13+
{
14+
public:
15+
SerializationInterface(PointerRange<char> buffer);
16+
SerializationInterface(MemoryBuffer &buffer);
17+
template<uintPtr Capacity>
18+
SerializationInterface(InplaceBuffer<Capacity> &inplace)
19+
{
20+
origin = &inplace;
21+
getData = +[](void *origin) -> char * { return ((InplaceBuffer<Capacity> *)origin)->data; };
22+
getSize = +[](void *origin) -> uintPtr { return ((InplaceBuffer<Capacity> *)origin)->size; };
23+
setSize = +[](void *origin, uintPtr size) -> void { ((InplaceBuffer<Capacity> *)origin)->size = size; };
24+
}
25+
26+
using GetData = char *(*)(void *);
27+
using GetSize = uintPtr (*)(void *);
28+
using SetSize = void (*)(void *, uintPtr);
29+
GetData getData = nullptr;
30+
GetSize getSize = nullptr;
31+
SetSize setSize = nullptr;
32+
void *origin = nullptr;
33+
};
34+
35+
}
36+
1037
struct CAGE_CORE_API Serializer : private Noncopyable
1138
{
1239
explicit Serializer(PointerRange<char> buffer);
13-
explicit Serializer(MemoryBuffer &buffer, uintPtr size = m);
40+
explicit Serializer(MemoryBuffer &buffer, uintPtr capacity = m);
41+
template<uintPtr Capacity>
42+
explicit Serializer(InplaceBuffer<Capacity> &inplace) : Serializer(inplace, 0, Capacity)
43+
{}
44+
explicit Serializer(privat::SerializationInterface interface, uintPtr offset, uintPtr capacity);
1445

15-
uintPtr available() const; // number of bytes still available in the buffer (valid only if the maximum size was given in the constructor)
46+
uintPtr available() const; // number of bytes still available in the buffer (valid only if the capacity was provided in the constructor)
1647
void write(PointerRange<const char> buffer);
17-
PointerRange<char> write(uintPtr size); // use with care!
48+
PointerRange<char> write(uintPtr size); // use with care! - future writes may invalidate the pointer
1849
void writeLine(const String &line);
1950
Serializer reserve(uintPtr s);
2051

2152
private:
22-
explicit Serializer(MemoryBuffer *buffer, char *data, uintPtr offset, uintPtr size);
23-
PointerRange<char> advance(uintPtr s); // future writes may cause the MemoryBuffer to reallocate invalidating the PointerRange
24-
25-
MemoryBuffer *buffer = nullptr;
26-
char *data = nullptr;
53+
privat::SerializationInterface interface;
2754
uintPtr offset = 0; // current position in the buffer
28-
uintPtr size = 0; // max size of the buffer
55+
uintPtr capacity = 0; // max size of the buffer
2956
};
3057

3158
struct CAGE_CORE_API Deserializer : private Noncopyable

sources/libcore/serialization.cpp

+42-29
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,55 @@
44

55
namespace cage
66
{
7-
Serializer::Serializer(PointerRange<char> buffer) : data(buffer.data()), size(buffer.size()) {}
7+
namespace privat
8+
{
9+
SerializationInterface::SerializationInterface(PointerRange<char> buffer)
10+
{
11+
origin = buffer.data();
12+
getData = +[](void *origin) -> char * { return (char *)origin; };
13+
}
14+
15+
SerializationInterface::SerializationInterface(MemoryBuffer &buffer)
16+
{
17+
origin = &buffer;
18+
getData = +[](void *origin) -> char * { return ((MemoryBuffer *)origin)->data(); };
19+
getSize = +[](void *origin) -> uintPtr { return ((MemoryBuffer *)origin)->size(); };
20+
setSize = +[](void *origin, uintPtr size) -> void { ((MemoryBuffer *)origin)->resizeSmart(size); };
21+
}
22+
}
23+
24+
Serializer::Serializer(PointerRange<char> buffer) : interface(buffer), capacity(buffer.size()) {}
825

9-
Serializer::Serializer(MemoryBuffer &buffer, uintPtr size) : buffer(&buffer), size(size == m && buffer.size() != 0 ? buffer.size() : size) {}
26+
Serializer::Serializer(MemoryBuffer &buffer, uintPtr capacity) : interface(buffer), capacity(capacity == m && buffer.size() != 0 ? buffer.size() : capacity) {}
1027

11-
Serializer::Serializer(MemoryBuffer *buffer, char *data, uintPtr offset, uintPtr size) : buffer(buffer), data(data), offset(offset), size(size) {}
28+
Serializer::Serializer(privat::SerializationInterface interface, uintPtr offset, uintPtr capacity) : interface(interface), offset(offset), capacity(capacity) {}
1229

1330
uintPtr Serializer::available() const
1431
{
15-
CAGE_ASSERT(size >= offset);
16-
return size - offset;
32+
CAGE_ASSERT(capacity >= offset);
33+
return capacity - offset;
1734
}
1835

1936
void Serializer::write(PointerRange<const char> buffer)
2037
{
21-
auto dst = advance(buffer.size());
22-
if (!buffer.empty())
23-
detail::memcpy(dst.data(), buffer.data(), buffer.size());
38+
if (buffer.empty())
39+
return;
40+
auto dst = write(buffer.size());
41+
detail::memcpy(dst.data(), buffer.data(), buffer.size());
2442
}
2543

2644
PointerRange<char> Serializer::write(uintPtr size)
2745
{
28-
return advance(size);
46+
if (available() < size)
47+
CAGE_THROW_ERROR(Exception, "serialization beyond available space");
48+
if (interface.getSize && interface.getSize(interface.origin) < offset + size)
49+
{
50+
CAGE_ASSERT(interface.setSize);
51+
interface.setSize(interface.origin, offset + size);
52+
}
53+
char *dst = interface.getData(interface.origin) + offset;
54+
offset += size;
55+
return { dst, dst + size };
2956
}
3057

3158
void Serializer::writeLine(const String &line)
@@ -36,23 +63,9 @@ namespace cage
3663

3764
Serializer Serializer::reserve(uintPtr s)
3865
{
39-
uintPtr o = offset;
40-
advance(s);
41-
return Serializer(buffer, data, o, offset);
42-
}
43-
44-
PointerRange<char> Serializer::advance(uintPtr s)
45-
{
46-
if (available() < s)
47-
CAGE_THROW_ERROR(Exception, "serialization beyond available space");
48-
if (!data)
49-
{
50-
if (buffer->size() < offset + s)
51-
buffer->resizeSmart(offset + s);
52-
}
53-
char *dst = (data ? data : buffer->data()) + offset;
54-
offset += s;
55-
return { dst, dst + s };
66+
const uintPtr o = offset;
67+
write(s);
68+
return Serializer(interface, o, offset);
5669
}
5770

5871
Deserializer::Deserializer(PointerRange<const char> buffer) : data(buffer.data()), size(buffer.size()) {}
@@ -85,7 +98,7 @@ namespace cage
8598
{
8699
const uintPtr a = available();
87100
PointerRange<const char> pr = { data + offset, data + offset + a };
88-
uintPtr l = detail::readLine(line, pr, false);
101+
const uintPtr l = detail::readLine(line, pr, false);
89102
if (l)
90103
{
91104
offset += l;
@@ -98,7 +111,7 @@ namespace cage
98111
{
99112
const uintPtr a = available();
100113
PointerRange<const char> pr = { data + offset, data + offset + a };
101-
uintPtr l = detail::readLine(line, pr, false);
114+
const uintPtr l = detail::readLine(line, pr, false);
102115
if (l)
103116
{
104117
offset += l;
@@ -109,7 +122,7 @@ namespace cage
109122

110123
Deserializer Deserializer::subview(uintPtr s)
111124
{
112-
uintPtr o = offset;
125+
const uintPtr o = offset;
113126
read(s);
114127
return Deserializer(data, o, offset);
115128
}

sources/test-core/serialization.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,16 @@ void testSerialization()
191191
functionTakingCharPointer(items.data(), items.size());
192192
}
193193
}
194+
195+
{
196+
CAGE_TESTCASE("inplace buffer");
197+
InplaceBuffer b1;
198+
Serializer ser(b1);
199+
int arr[3] = { 1, 2, 3 };
200+
ser << arr;
201+
arr[0] = arr[1] = arr[2] = 0;
202+
Deserializer des(b1);
203+
des >> arr;
204+
CAGE_TEST(arr[0] == 1 && arr[1] == 2 && arr[2] == 3);
205+
}
194206
}

0 commit comments

Comments
 (0)