Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
BinarySerializer.h
Go to the documentation of this file.
1/* Copyright (C) 2021 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDED_BINARYSERIALIZER
19#define INCLUDED_BINARYSERIALIZER
20
21#include "ISerializer.h"
22
23#include "lib/byte_order.h"
24
26
27#include <ostream>
28#include <streambuf>
29
30/**
31 * Wrapper for redirecting ostream writes to CBinarySerializer's impl
32 */
33template<typename T>
34class CSerializerStreamBuf : public std::streambuf
35{
38 char m_Buffer[2048];
39public:
42 {
44 }
45
46protected:
47 // Override overflow and sync, because older versions of libc++ streams
48 // write strings as individual characters, then xsputn is never called
49 int overflow(int ch)
50 {
51 if (ch == traits_type::eof())
52 return traits_type::not_eof(ch);
53
54 ENSURE(pptr() <= epptr());
55 *pptr() = ch;
56 pbump(1);
57 sync();
58 return ch;
59 }
60
61 int sync()
62 {
63 std::ptrdiff_t n = pptr() - pbase();
64 if (n != 0)
65 {
66 pbump(-n);
67 m_SerializerImpl.Put("stream", reinterpret_cast<const u8*> (pbase()), n);
68 }
69 return 0;
70 }
71
72 std::streamsize xsputn(const char* s, std::streamsize n)
73 {
74 m_SerializerImpl.Put("stream", reinterpret_cast<const u8*> (s), n);
75 return n;
76 }
77};
78
79/**
80 * PutScriptVal implementation details.
81 * (Split out from the main class because it's too big to be inlined.)
82 */
84{
85public:
86 CBinarySerializerScriptImpl(const ScriptInterface& scriptInterface, ISerializer& serializer);
88
89 void ScriptString(const char* name, JS::HandleString string);
90 void HandleScriptVal(JS::HandleValue val);
91private:
92 static void Trace(JSTracer* trc, void* data);
93
96
97 using ObjectTagMap = JS::GCHashMap<JS::Heap<JSObject*>, u32, js::MovableCellHasher<JSObject*>, js::SystemAllocPolicy>;
100 u32 GetScriptBackrefTag(JS::HandleObject obj);
101};
102
103/**
104 * Serialize to a binary stream. T must just implement the Put() method.
105 * (We use this templated approach to allow compiler inlining.)
106 */
107template <typename T>
109{
111public:
112 CBinarySerializer(const ScriptInterface& scriptInterface) :
113 m_ScriptImpl(new CBinarySerializerScriptImpl(scriptInterface, *this)),
116 {
117 }
118
119 template <typename A>
120 CBinarySerializer(const ScriptInterface& scriptInterface, A& a) :
121 m_ScriptImpl(new CBinarySerializerScriptImpl(scriptInterface, *this)),
122 m_Impl(a),
125 {
126 }
127
128protected:
129 /*
130 The Put* implementations here are designed for subclasses
131 that want an efficient, portable, deserializable representation.
132 (Subclasses with different requirements should override these methods.)
133
134 Numbers are converted to little-endian byte strings, for portability
135 and efficiency.
136
137 Data is not aligned, for storage efficiency.
138 */
139
140 virtual void PutNumber(const char* name, uint8_t value)
141 {
142 m_Impl.Put(name, (const u8*)&value, sizeof(uint8_t));
143 }
144
145 virtual void PutNumber(const char* name, int8_t value)
146 {
147 m_Impl.Put(name, (const u8*)&value, sizeof(int8_t));
148 }
149
150 virtual void PutNumber(const char* name, uint16_t value)
151 {
152 uint16_t v = to_le16(value);
153 m_Impl.Put(name, (const u8*)&v, sizeof(uint16_t));
154 }
155
156 virtual void PutNumber(const char* name, int16_t value)
157 {
158 int16_t v = (i16)to_le16((u16)value);
159 m_Impl.Put(name, (const u8*)&v, sizeof(int16_t));
160 }
161
162 virtual void PutNumber(const char* name, uint32_t value)
163 {
164 uint32_t v = to_le32(value);
165 m_Impl.Put(name, (const u8*)&v, sizeof(uint32_t));
166 }
167
168 virtual void PutNumber(const char* name, int32_t value)
169 {
170 int32_t v = (i32)to_le32((u32)value);
171 m_Impl.Put(name, (const u8*)&v, sizeof(int32_t));
172 }
173
174 virtual void PutNumber(const char* name, float value)
175 {
176 m_Impl.Put(name, (const u8*)&value, sizeof(float));
177 }
178
179 virtual void PutNumber(const char* name, double value)
180 {
181 m_Impl.Put(name, (const u8*)&value, sizeof(double));
182 }
183
184 virtual void PutNumber(const char* name, fixed value)
185 {
186 int32_t v = (i32)to_le32((u32)value.GetInternalValue());
187 m_Impl.Put(name, (const u8*)&v, sizeof(int32_t));
188 }
189
190 virtual void PutBool(const char* name, bool value)
191 {
192 NumberU8(name, value ? 1 : 0, 0, 1);
193 }
194
195 virtual void PutString(const char* name, const std::string& value)
196 {
197 // TODO: maybe should intern strings, particularly to save space with script property names
198 PutNumber("string length", (uint32_t)value.length());
199 m_Impl.Put(name, (u8*)value.data(), value.length());
200 }
201
202 virtual void PutScriptVal(const char* UNUSED(name), JS::MutableHandleValue value)
203 {
204 m_ScriptImpl->HandleScriptVal(value);
205 }
206
207 virtual void PutRaw(const char* name, const u8* data, size_t len)
208 {
209 m_Impl.Put(name, data, len);
210 }
211
212 virtual std::ostream& GetStream()
213 {
214 return m_RawStream;
215 }
216
217protected:
219
220private:
221 std::unique_ptr<CBinarySerializerScriptImpl> m_ScriptImpl;
222
224 std::ostream m_RawStream;
225};
226
227#endif // INCLUDED_BINARYSERIALIZER
#define to_le16(x)
Definition: byte_order.h:77
#define to_le32(x)
Definition: byte_order.h:78
PutScriptVal implementation details.
Definition: BinarySerializer.h:84
void ScriptString(const char *name, JS::HandleString string)
Definition: BinarySerializer.cpp:433
~CBinarySerializerScriptImpl()
Definition: BinarySerializer.cpp:67
void HandleScriptVal(JS::HandleValue val)
Definition: BinarySerializer.cpp:73
const ScriptInterface & m_ScriptInterface
Definition: BinarySerializer.h:94
u32 GetScriptBackrefTag(JS::HandleObject obj)
Definition: BinarySerializer.cpp:471
ObjectTagMap m_ScriptBackrefTags
Definition: BinarySerializer.h:98
static void Trace(JSTracer *trc, void *data)
Definition: BinarySerializer.cpp:465
JS::GCHashMap< JS::Heap< JSObject * >, u32, js::MovableCellHasher< JSObject * >, js::SystemAllocPolicy > ObjectTagMap
Definition: BinarySerializer.h:97
u32 m_ScriptBackrefsNext
Definition: BinarySerializer.h:99
ISerializer & m_Serializer
Definition: BinarySerializer.h:95
CBinarySerializerScriptImpl(const ScriptInterface &scriptInterface, ISerializer &serializer)
Definition: BinarySerializer.cpp:60
Serialize to a binary stream.
Definition: BinarySerializer.h:109
std::unique_ptr< CBinarySerializerScriptImpl > m_ScriptImpl
Definition: BinarySerializer.h:221
virtual void PutScriptVal(const char *name, JS::MutableHandleValue value)
Definition: BinarySerializer.h:202
T m_Impl
Definition: BinarySerializer.h:218
virtual void PutNumber(const char *name, float value)
Definition: BinarySerializer.h:174
virtual void PutNumber(const char *name, int8_t value)
Definition: BinarySerializer.h:145
std::ostream m_RawStream
Definition: BinarySerializer.h:224
virtual void PutNumber(const char *name, int16_t value)
Definition: BinarySerializer.h:156
NONCOPYABLE(CBinarySerializer)
CSerializerStreamBuf< T > m_RawStreamBuf
Definition: BinarySerializer.h:223
virtual void PutNumber(const char *name, fixed value)
Definition: BinarySerializer.h:184
virtual void PutNumber(const char *name, uint16_t value)
Definition: BinarySerializer.h:150
virtual void PutRaw(const char *name, const u8 *data, size_t len)
Definition: BinarySerializer.h:207
virtual void PutNumber(const char *name, uint8_t value)
Definition: BinarySerializer.h:140
virtual void PutNumber(const char *name, uint32_t value)
Definition: BinarySerializer.h:162
virtual void PutString(const char *name, const std::string &value)
Definition: BinarySerializer.h:195
virtual std::ostream & GetStream()
Returns a stream which can be used to serialize data directly.
Definition: BinarySerializer.h:212
CBinarySerializer(const ScriptInterface &scriptInterface, A &a)
Definition: BinarySerializer.h:120
virtual void PutNumber(const char *name, double value)
Definition: BinarySerializer.h:179
virtual void PutBool(const char *name, bool value)
Definition: BinarySerializer.h:190
CBinarySerializer(const ScriptInterface &scriptInterface)
Definition: BinarySerializer.h:112
virtual void PutNumber(const char *name, int32_t value)
Definition: BinarySerializer.h:168
A simple fixed-point number class.
Definition: Fixed.h:120
T GetInternalValue() const
Definition: Fixed.h:135
Wrapper for redirecting ostream writes to CBinarySerializer's impl.
Definition: BinarySerializer.h:35
NONCOPYABLE(CSerializerStreamBuf)
int sync()
Definition: BinarySerializer.h:61
char m_Buffer[2048]
Definition: BinarySerializer.h:38
int overflow(int ch)
Definition: BinarySerializer.h:49
CSerializerStreamBuf(T &impl)
Definition: BinarySerializer.h:40
std::streamsize xsputn(const char *s, std::streamsize n)
Definition: BinarySerializer.h:72
T & m_SerializerImpl
Definition: BinarySerializer.h:37
Serialization interface; see serialization overview.
Definition: ISerializer.h:121
void NumberU8(const char *name, uint8_t value, uint8_t lower, uint8_t upper)
Serialize a number, which must be lower <= value <= upper.
Definition: ISerializer.cpp:28
Abstraction around a SpiderMonkey JS::Realm.
Definition: ScriptInterface.h:72
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning.
Definition: code_annotation.h:40
#define ARRAY_SIZE(name)
Definition: code_annotation.h:350
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
Definition: debug.h:277
#define T(string_literal)
Definition: secure_crt.cpp:77
int32_t i32
Definition: types.h:34
uint8_t u8
Definition: types.h:37
uint16_t u16
Definition: types.h:38
int16_t i16
Definition: types.h:33
uint32_t u32
Definition: types.h:39
unsigned short uint16_t
Definition: wposix_types.h:52
unsigned int uint32_t
Definition: wposix_types.h:53
short int16_t
Definition: wposix_types.h:38
unsigned char uint8_t
Definition: wposix_types.h:51
signed char int8_t
Definition: wposix_types.h:37