Pyrogenesis  trunk
BinarySerializer.h
Go to the documentation of this file.
1 /* Copyright (C) 2015 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 
24 
25 #include "lib/byte_order.h"
26 #include "lib/allocators/arena.h"
27 
28 #include <map>
29 
30 /**
31  * Wrapper for redirecting ostream writes to CBinarySerializer's impl
32  */
33 template<typename T>
34 class CSerializerStreamBuf : public std::streambuf
35 {
38  char m_Buffer[2048];
39 public:
41  m_SerializerImpl(impl)
42  {
43  setp(m_Buffer, m_Buffer + ARRAY_SIZE(m_Buffer) - 1);
44  }
45 
46 protected:
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 {
85 public:
86  CBinarySerializerScriptImpl(ScriptInterface& scriptInterface, ISerializer& serializer);
87 
88  void ScriptString(const char* name, JS::HandleString string);
89  void HandleScriptVal(JS::HandleValue val);
90  void SetSerializablePrototypes(shared_ptr<ObjectIdCache<std::wstring> > prototypes);
91 private:
94 
97  u32 GetScriptBackrefTag(JS::HandleObject obj);
98 
99  shared_ptr<ObjectIdCache<std::wstring> > m_SerializablePrototypes;
100 
101  bool IsSerializablePrototype(JS::HandleObject prototype);
102  std::wstring GetPrototypeName(JS::HandleObject prototype);
103 };
104 
105 /**
106  * Serialize to a binary stream. T must just implement the Put() method.
107  * (We use this templated approach to allow compiler inlining.)
108  */
109 template <typename T>
111 {
113 public:
114  CBinarySerializer(ScriptInterface& scriptInterface) :
115  m_ScriptImpl(new CBinarySerializerScriptImpl(scriptInterface, *this)),
116  m_RawStreamBuf(m_Impl),
117  m_RawStream(&m_RawStreamBuf)
118  {
119  }
120 
121  template <typename A>
122  CBinarySerializer(ScriptInterface& scriptInterface, A& a) :
123  m_ScriptImpl(new CBinarySerializerScriptImpl(scriptInterface, *this)),
124  m_Impl(a),
125  m_RawStreamBuf(m_Impl),
126  m_RawStream(&m_RawStreamBuf)
127  {
128  }
129 
130  virtual void SetSerializablePrototypes(shared_ptr<ObjectIdCache<std::wstring> >& prototypes)
131  {
132  m_ScriptImpl->SetSerializablePrototypes(prototypes);
133  }
134 
135 protected:
136  /*
137  The Put* implementations here are designed for subclasses
138  that want an efficient, portable, deserializable representation.
139  (Subclasses with different requirements should override these methods.)
140 
141  Numbers are converted to little-endian byte strings, for portability
142  and efficiency.
143 
144  Data is not aligned, for storage efficiency.
145  */
146 
147  virtual void PutNumber(const char* name, uint8_t value)
148  {
149  m_Impl.Put(name, (const u8*)&value, sizeof(uint8_t));
150  }
151 
152  virtual void PutNumber(const char* name, int8_t value)
153  {
154  m_Impl.Put(name, (const u8*)&value, sizeof(int8_t));
155  }
156 
157  virtual void PutNumber(const char* name, uint16_t value)
158  {
159  uint16_t v = to_le16(value);
160  m_Impl.Put(name, (const u8*)&v, sizeof(uint16_t));
161  }
162 
163  virtual void PutNumber(const char* name, int16_t value)
164  {
165  int16_t v = (i16)to_le16((u16)value);
166  m_Impl.Put(name, (const u8*)&v, sizeof(int16_t));
167  }
168 
169  virtual void PutNumber(const char* name, uint32_t value)
170  {
171  uint32_t v = to_le32(value);
172  m_Impl.Put(name, (const u8*)&v, sizeof(uint32_t));
173  }
174 
175  virtual void PutNumber(const char* name, int32_t value)
176  {
177  int32_t v = (i32)to_le32((u32)value);
178  m_Impl.Put(name, (const u8*)&v, sizeof(int32_t));
179  }
180 
181  virtual void PutNumber(const char* name, float value)
182  {
183  m_Impl.Put(name, (const u8*)&value, sizeof(float));
184  }
185 
186  virtual void PutNumber(const char* name, double value)
187  {
188  m_Impl.Put(name, (const u8*)&value, sizeof(double));
189  }
190 
191  virtual void PutNumber(const char* name, fixed value)
192  {
193  int32_t v = (i32)to_le32((u32)value.GetInternalValue());
194  m_Impl.Put(name, (const u8*)&v, sizeof(int32_t));
195  }
196 
197  virtual void PutBool(const char* name, bool value)
198  {
199  NumberU8(name, value ? 1 : 0, 0, 1);
200  }
201 
202  virtual void PutString(const char* name, const std::string& value)
203  {
204  // TODO: maybe should intern strings, particularly to save space with script property names
205  PutNumber("string length", (uint32_t)value.length());
206  m_Impl.Put(name, (u8*)value.data(), value.length());
207  }
208 
209  virtual void PutScriptVal(const char* UNUSED(name), JS::MutableHandleValue value)
210  {
211  m_ScriptImpl->HandleScriptVal(value);
212  }
213 
214  virtual void PutRaw(const char* name, const u8* data, size_t len)
215  {
216  m_Impl.Put(name, data, len);
217  }
218 
219  virtual std::ostream& GetStream()
220  {
221  return m_RawStream;
222  }
223 
224 protected:
226 
227 private:
228  std::unique_ptr<CBinarySerializerScriptImpl> m_ScriptImpl;
229 
231  std::ostream m_RawStream;
232 };
233 
234 #endif // INCLUDED_BINARYSERIALIZER
signed char int8_t
Definition: wposix_types.h:37
A simple fixed-point number class.
Definition: Fixed.h:115
int overflow(int ch)
Definition: BinarySerializer.h:49
char m_Buffer[2048]
Definition: BinarySerializer.h:38
CSerializerStreamBuf< T > m_RawStreamBuf
Definition: BinarySerializer.h:230
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
Definition: code_annotation.h:38
ScriptInterface & m_ScriptInterface
Definition: BinarySerializer.h:92
uint16_t u16
Definition: types.h:38
Serialization interface; see serialization overview.
Definition: ISerializer.h:120
#define to_le16(x)
Definition: byte_order.h:77
shared_ptr< ObjectIdCache< std::wstring > > m_SerializablePrototypes
Definition: BinarySerializer.h:99
short int16_t
Definition: wposix_types.h:38
virtual void PutNumber(const char *name, int32_t value)
Definition: BinarySerializer.h:175
virtual void PutNumber(const char *name, fixed value)
Definition: BinarySerializer.h:191
virtual void PutNumber(const char *name, float value)
Definition: BinarySerializer.h:181
ObjectIdCache< u32 > m_ScriptBackrefs
Definition: BinarySerializer.h:95
T GetInternalValue() const
Definition: Fixed.h:131
ISerializer & m_Serializer
Definition: BinarySerializer.h:93
std::ostream m_RawStream
Definition: BinarySerializer.h:231
virtual void PutRaw(const char *name, const u8 *data, size_t len)
Definition: BinarySerializer.h:214
virtual void PutBool(const char *name, bool value)
Definition: BinarySerializer.h:197
uint8_t u8
Definition: types.h:37
#define ARRAY_SIZE(name)
Definition: code_annotation.h:336
PutScriptVal implementation details.
Definition: BinarySerializer.h:83
virtual void PutNumber(const char *name, uint32_t value)
Definition: BinarySerializer.h:169
u32 m_ScriptBackrefsNext
Definition: BinarySerializer.h:96
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
Definition: debug.h:287
uint32_t u32
Definition: types.h:39
std::streamsize xsputn(const char *s, std::streamsize n)
Definition: BinarySerializer.h:72
T & m_SerializerImpl
Definition: BinarySerializer.h:37
virtual void PutString(const char *name, const std::string &value)
Definition: BinarySerializer.h:202
#define to_le32(x)
Definition: byte_order.h:78
unsigned char uint8_t
Definition: wposix_types.h:51
int sync()
Definition: BinarySerializer.h:61
virtual void SetSerializablePrototypes(shared_ptr< ObjectIdCache< std::wstring > > &prototypes)
Definition: BinarySerializer.h:130
virtual void PutNumber(const char *name, int8_t value)
Definition: BinarySerializer.h:152
CBinarySerializer(ScriptInterface &scriptInterface, A &a)
Definition: BinarySerializer.h:122
#define T(string_literal)
Definition: secure_crt.cpp:76
int32_t i32
Definition: types.h:34
NONCOPYABLE(CSerializerStreamBuf)
virtual void PutNumber(const char *name, int16_t value)
Definition: BinarySerializer.h:163
virtual std::ostream & GetStream()
Returns a stream which can be used to serialize data directly.
Definition: BinarySerializer.h:219
unsigned int uint32_t
Definition: wposix_types.h:53
T m_Impl
Definition: BinarySerializer.h:225
virtual void PutNumber(const char *name, uint16_t value)
Definition: BinarySerializer.h:157
Abstraction around a SpiderMonkey JSContext.
Definition: ScriptInterface.h:71
int16_t i16
Definition: types.h:33
Serialize to a binary stream.
Definition: BinarySerializer.h:110
unsigned short uint16_t
Definition: wposix_types.h:52
Wrapper for redirecting ostream writes to CBinarySerializer&#39;s impl.
Definition: BinarySerializer.h:34
Providing a map-like structure with JSObject pointers (actually their hash) as keys with correct garb...
Definition: ObjectToIDMap.h:29
virtual void PutNumber(const char *name, double value)
Definition: BinarySerializer.h:186
virtual void PutScriptVal(const char *name, JS::MutableHandleValue value)
Definition: BinarySerializer.h:209
CBinarySerializer(ScriptInterface &scriptInterface)
Definition: BinarySerializer.h:114
std::unique_ptr< CBinarySerializerScriptImpl > m_ScriptImpl
Definition: BinarySerializer.h:228
virtual void PutNumber(const char *name, uint8_t value)
Definition: BinarySerializer.h:147
CSerializerStreamBuf(T &impl)
Definition: BinarySerializer.h:40