Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BinarySerializer.h
Go to the documentation of this file.
1 /* Copyright (C) 2013 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 public:
40  m_SerializerImpl(impl)
41  {
42  }
43 
44  std::streamsize xsputn(const char* s, std::streamsize n)
45  {
46  m_SerializerImpl.Put("stream", reinterpret_cast<const u8*> (s), n);
47  return n;
48  }
49 };
50 
51 /**
52  * PutScriptVal implementation details.
53  * (Split out from the main class because it's too big to be inlined.)
54  */
56 {
57 public:
58  CBinarySerializerScriptImpl(ScriptInterface& scriptInterface, ISerializer& serializer);
59 
60  void ScriptString(const char* name, JSString* string);
61  void HandleScriptVal(jsval val);
62  void SetSerializablePrototypes(std::map<JSObject*, std::wstring>& prototypes);
63 private:
66 
67  // Pooling helps since we do a lot of short-lived allocations
69  typedef std::map<JSObject*, u32, std::less<JSObject*>, ScriptBackrefsAlloc> backrefs_t;
70 
74  u32 GetScriptBackrefTag(JSObject* obj);
75 
77 
78  std::map<JSObject*, std::wstring> m_SerializablePrototypes;
79 
80  bool IsSerializablePrototype(JSObject* prototype);
81  std::wstring GetPrototypeName(JSObject* prototype);
82 };
83 
84 /**
85  * Serialize to a binary stream. T must just implement the Put() method.
86  * (We use this templated approach to allow compiler inlining.)
87  */
88 template <typename T>
90 {
92 public:
93  CBinarySerializer(ScriptInterface& scriptInterface) :
94  m_ScriptImpl(new CBinarySerializerScriptImpl(scriptInterface, *this)),
97  {
98  }
99 
100  template <typename A>
101  CBinarySerializer(ScriptInterface& scriptInterface, A& a) :
102  m_ScriptImpl(new CBinarySerializerScriptImpl(scriptInterface, *this)),
103  m_Impl(a),
106  {
107  }
108 
109  virtual void SetSerializablePrototypes(std::map<JSObject*, std::wstring>& prototypes)
110  {
111  m_ScriptImpl->SetSerializablePrototypes(prototypes);
112  }
113 
114 protected:
115  /*
116  The Put* implementations here are designed for subclasses
117  that want an efficient, portable, deserializable representation.
118  (Subclasses with different requirements should override these methods.)
119 
120  Numbers are converted to little-endian byte strings, for portability
121  and efficiency.
122 
123  Data is not aligned, for storage efficiency.
124  */
125 
126  virtual void PutNumber(const char* name, uint8_t value)
127  {
128  m_Impl.Put(name, (const u8*)&value, sizeof(uint8_t));
129  }
130 
131  virtual void PutNumber(const char* name, int8_t value)
132  {
133  m_Impl.Put(name, (const u8*)&value, sizeof(int8_t));
134  }
135 
136  virtual void PutNumber(const char* name, uint16_t value)
137  {
138  uint16_t v = to_le16(value);
139  m_Impl.Put(name, (const u8*)&v, sizeof(uint16_t));
140  }
141 
142  virtual void PutNumber(const char* name, int16_t value)
143  {
144  int16_t v = (i16)to_le16((u16)value);
145  m_Impl.Put(name, (const u8*)&v, sizeof(int16_t));
146  }
147 
148  virtual void PutNumber(const char* name, uint32_t value)
149  {
150  uint32_t v = to_le32(value);
151  m_Impl.Put(name, (const u8*)&v, sizeof(uint32_t));
152  }
153 
154  virtual void PutNumber(const char* name, int32_t value)
155  {
156  int32_t v = (i32)to_le32((u32)value);
157  m_Impl.Put(name, (const u8*)&v, sizeof(int32_t));
158  }
159 
160  virtual void PutNumber(const char* name, float value)
161  {
162  m_Impl.Put(name, (const u8*)&value, sizeof(float));
163  }
164 
165  virtual void PutNumber(const char* name, double value)
166  {
167  m_Impl.Put(name, (const u8*)&value, sizeof(double));
168  }
169 
170  virtual void PutNumber(const char* name, fixed value)
171  {
172  int32_t v = (i32)to_le32((u32)value.GetInternalValue());
173  m_Impl.Put(name, (const u8*)&v, sizeof(int32_t));
174  }
175 
176  virtual void PutBool(const char* name, bool value)
177  {
178  NumberU8(name, value ? 1 : 0, 0, 1);
179  }
180 
181  virtual void PutString(const char* name, const std::string& value)
182  {
183  // TODO: maybe should intern strings, particularly to save space with script property names
184  PutNumber("string length", (uint32_t)value.length());
185  m_Impl.Put(name, (u8*)value.data(), value.length());
186  }
187 
188  virtual void PutScriptVal(const char* UNUSED(name), jsval value)
189  {
190  m_ScriptImpl->HandleScriptVal(value);
191  }
192 
193  virtual void PutRaw(const char* name, const u8* data, size_t len)
194  {
195  m_Impl.Put(name, data, len);
196  }
197 
198  virtual std::ostream& GetStream()
199  {
200  return m_RawStream;
201  }
202 
203 protected:
205 
206 private:
207  std::auto_ptr<CBinarySerializerScriptImpl> m_ScriptImpl;
208 
210  std::ostream m_RawStream;
211 };
212 
213 #endif // INCLUDED_BINARYSERIALIZER
signed char int8_t
Definition: wposix_types.h:37
#define u8
Definition: types.h:39
A simple fixed-point number class.
Definition: Fixed.h:115
CSerializerStreamBuf< T > m_RawStreamBuf
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
ScriptInterface & m_ScriptInterface
virtual void PutScriptVal(const char *name, jsval value)
#define i32
Definition: types.h:36
Serialization interface; see serialization overview.
Definition: ISerializer.h:120
#define to_le16(x)
Definition: byte_order.h:77
short int16_t
Definition: wposix_types.h:38
virtual void PutNumber(const char *name, int32_t value)
virtual void PutNumber(const char *name, fixed value)
virtual void PutNumber(const char *name, float value)
ProxyAllocator< std::pair< JSObject *const, u32 >, Allocators::DynamicArena > ScriptBackrefsAlloc
T GetInternalValue() const
Definition: Fixed.h:131
std::ostream m_RawStream
virtual void PutRaw(const char *name, const u8 *data, size_t len)
virtual void PutBool(const char *name, bool value)
#define i16
Definition: types.h:35
std::map< JSObject *, u32, std::less< JSObject * >, ScriptBackrefsAlloc > backrefs_t
PutScriptVal implementation details.
void ScriptString(const char *name, JSString *string)
virtual void PutNumber(const char *name, uint32_t value)
std::streamsize xsputn(const char *s, std::streamsize n)
virtual void PutString(const char *name, const std::string &value)
#define to_le32(x)
Definition: byte_order.h:78
void SetSerializablePrototypes(std::map< JSObject *, std::wstring > &prototypes)
unsigned char uint8_t
Definition: wposix_types.h:51
Allocators::DynamicArena m_ScriptBackrefsArena
virtual void SetSerializablePrototypes(std::map< JSObject *, std::wstring > &prototypes)
virtual void PutNumber(const char *name, int8_t value)
CBinarySerializer(ScriptInterface &scriptInterface, A &a)
std::map< JSObject *, std::wstring > m_SerializablePrototypes
#define T(string_literal)
Definition: secure_crt.cpp:70
CBinarySerializerScriptImpl(ScriptInterface &scriptInterface, ISerializer &serializer)
NONCOPYABLE(CSerializerStreamBuf)
std::auto_ptr< CBinarySerializerScriptImpl > m_ScriptImpl
virtual void PutNumber(const char *name, int16_t value)
virtual std::ostream & GetStream()
Returns a stream which can be used to serialize data directly.
#define u16
Definition: types.h:40
fully STL-compatible allocator that simply draws upon another Allocator.
#define u32
Definition: types.h:41
unsigned int uint32_t
Definition: wposix_types.h:53
virtual void PutNumber(const char *name, uint16_t value)
allocator design parameters:
Definition: arena.h:93
Abstraction around a SpiderMonkey JSContext.
Serialize to a binary stream.
NONCOPYABLE(CBinarySerializer)
unsigned short uint16_t
Definition: wposix_types.h:52
Wrapper for redirecting ostream writes to CBinarySerializer&#39;s impl.
std::wstring GetPrototypeName(JSObject *prototype)
virtual void PutNumber(const char *name, double value)
void NumberU8(const char *name, uint8_t value, uint8_t lower, uint8_t upper)
Serialize a number, which must be lower &lt;= value &lt;= upper.
Definition: ISerializer.cpp:28
u32 GetScriptBackrefTag(JSObject *obj)
CBinarySerializer(ScriptInterface &scriptInterface)
Helper for rooting large groups of script values.
Definition: AutoRooters.h:31
virtual void PutNumber(const char *name, uint8_t value)
bool IsSerializablePrototype(JSObject *prototype)