1 | #include <stdint.h>
|
---|
2 | #include "./BSER.hh"
|
---|
3 |
|
---|
4 | BSERType decodeType(std::istream &iss) {
|
---|
5 | int8_t type;
|
---|
6 | iss.read(reinterpret_cast<char*>(&type), sizeof(type));
|
---|
7 | return (BSERType) type;
|
---|
8 | }
|
---|
9 |
|
---|
10 | void expectType(std::istream &iss, BSERType expected) {
|
---|
11 | BSERType got = decodeType(iss);
|
---|
12 | if (got != expected) {
|
---|
13 | throw std::runtime_error("Unexpected BSER type");
|
---|
14 | }
|
---|
15 | }
|
---|
16 |
|
---|
17 | void encodeType(std::ostream &oss, BSERType type) {
|
---|
18 | int8_t t = (int8_t)type;
|
---|
19 | oss.write(reinterpret_cast<char*>(&t), sizeof(t));
|
---|
20 | }
|
---|
21 |
|
---|
22 | template<typename T>
|
---|
23 | class Value : public BSERValue {
|
---|
24 | public:
|
---|
25 | T value;
|
---|
26 | Value(T val) {
|
---|
27 | value = val;
|
---|
28 | }
|
---|
29 |
|
---|
30 | Value() {}
|
---|
31 | };
|
---|
32 |
|
---|
33 | class BSERInteger : public Value<int64_t> {
|
---|
34 | public:
|
---|
35 | BSERInteger(int64_t value) : Value(value) {}
|
---|
36 | BSERInteger(std::istream &iss) {
|
---|
37 | int8_t int8;
|
---|
38 | int16_t int16;
|
---|
39 | int32_t int32;
|
---|
40 | int64_t int64;
|
---|
41 |
|
---|
42 | BSERType type = decodeType(iss);
|
---|
43 |
|
---|
44 | switch (type) {
|
---|
45 | case BSER_INT8:
|
---|
46 | iss.read(reinterpret_cast<char*>(&int8), sizeof(int8));
|
---|
47 | value = int8;
|
---|
48 | break;
|
---|
49 | case BSER_INT16:
|
---|
50 | iss.read(reinterpret_cast<char*>(&int16), sizeof(int16));
|
---|
51 | value = int16;
|
---|
52 | break;
|
---|
53 | case BSER_INT32:
|
---|
54 | iss.read(reinterpret_cast<char*>(&int32), sizeof(int32));
|
---|
55 | value = int32;
|
---|
56 | break;
|
---|
57 | case BSER_INT64:
|
---|
58 | iss.read(reinterpret_cast<char*>(&int64), sizeof(int64));
|
---|
59 | value = int64;
|
---|
60 | break;
|
---|
61 | default:
|
---|
62 | throw std::runtime_error("Invalid BSER int type");
|
---|
63 | }
|
---|
64 | }
|
---|
65 |
|
---|
66 | int64_t intValue() override {
|
---|
67 | return value;
|
---|
68 | }
|
---|
69 |
|
---|
70 | void encode(std::ostream &oss) override {
|
---|
71 | if (value <= INT8_MAX) {
|
---|
72 | encodeType(oss, BSER_INT8);
|
---|
73 | int8_t v = (int8_t)value;
|
---|
74 | oss.write(reinterpret_cast<char*>(&v), sizeof(v));
|
---|
75 | } else if (value <= INT16_MAX) {
|
---|
76 | encodeType(oss, BSER_INT16);
|
---|
77 | int16_t v = (int16_t)value;
|
---|
78 | oss.write(reinterpret_cast<char*>(&v), sizeof(v));
|
---|
79 | } else if (value <= INT32_MAX) {
|
---|
80 | encodeType(oss, BSER_INT32);
|
---|
81 | int32_t v = (int32_t)value;
|
---|
82 | oss.write(reinterpret_cast<char*>(&v), sizeof(v));
|
---|
83 | } else {
|
---|
84 | encodeType(oss, BSER_INT64);
|
---|
85 | oss.write(reinterpret_cast<char*>(&value), sizeof(value));
|
---|
86 | }
|
---|
87 | }
|
---|
88 | };
|
---|
89 |
|
---|
90 | class BSERArray : public Value<BSER::Array> {
|
---|
91 | public:
|
---|
92 | BSERArray() : Value() {}
|
---|
93 | BSERArray(BSER::Array value) : Value(value) {}
|
---|
94 | BSERArray(std::istream &iss) {
|
---|
95 | expectType(iss, BSER_ARRAY);
|
---|
96 | int64_t len = BSERInteger(iss).intValue();
|
---|
97 | for (int64_t i = 0; i < len; i++) {
|
---|
98 | value.push_back(BSER(iss));
|
---|
99 | }
|
---|
100 | }
|
---|
101 |
|
---|
102 | BSER::Array arrayValue() override {
|
---|
103 | return value;
|
---|
104 | }
|
---|
105 |
|
---|
106 | void encode(std::ostream &oss) override {
|
---|
107 | encodeType(oss, BSER_ARRAY);
|
---|
108 | BSERInteger(value.size()).encode(oss);
|
---|
109 | for (auto it = value.begin(); it != value.end(); it++) {
|
---|
110 | it->encode(oss);
|
---|
111 | }
|
---|
112 | }
|
---|
113 | };
|
---|
114 |
|
---|
115 | class BSERString : public Value<std::string> {
|
---|
116 | public:
|
---|
117 | BSERString(std::string value) : Value(value) {}
|
---|
118 | BSERString(std::istream &iss) {
|
---|
119 | expectType(iss, BSER_STRING);
|
---|
120 | int64_t len = BSERInteger(iss).intValue();
|
---|
121 | value.resize(len);
|
---|
122 | iss.read(&value[0], len);
|
---|
123 | }
|
---|
124 |
|
---|
125 | std::string stringValue() override {
|
---|
126 | return value;
|
---|
127 | }
|
---|
128 |
|
---|
129 | void encode(std::ostream &oss) override {
|
---|
130 | encodeType(oss, BSER_STRING);
|
---|
131 | BSERInteger(value.size()).encode(oss);
|
---|
132 | oss << value;
|
---|
133 | }
|
---|
134 | };
|
---|
135 |
|
---|
136 | class BSERObject : public Value<BSER::Object> {
|
---|
137 | public:
|
---|
138 | BSERObject() : Value() {}
|
---|
139 | BSERObject(BSER::Object value) : Value(value) {}
|
---|
140 | BSERObject(std::istream &iss) {
|
---|
141 | expectType(iss, BSER_OBJECT);
|
---|
142 | int64_t len = BSERInteger(iss).intValue();
|
---|
143 | for (int64_t i = 0; i < len; i++) {
|
---|
144 | auto key = BSERString(iss).stringValue();
|
---|
145 | auto val = BSER(iss);
|
---|
146 | value.emplace(key, val);
|
---|
147 | }
|
---|
148 | }
|
---|
149 |
|
---|
150 | BSER::Object objectValue() override {
|
---|
151 | return value;
|
---|
152 | }
|
---|
153 |
|
---|
154 | void encode(std::ostream &oss) override {
|
---|
155 | encodeType(oss, BSER_OBJECT);
|
---|
156 | BSERInteger(value.size()).encode(oss);
|
---|
157 | for (auto it = value.begin(); it != value.end(); it++) {
|
---|
158 | BSERString(it->first).encode(oss);
|
---|
159 | it->second.encode(oss);
|
---|
160 | }
|
---|
161 | }
|
---|
162 | };
|
---|
163 |
|
---|
164 | class BSERDouble : public Value<double> {
|
---|
165 | public:
|
---|
166 | BSERDouble(double value) : Value(value) {}
|
---|
167 | BSERDouble(std::istream &iss) {
|
---|
168 | expectType(iss, BSER_REAL);
|
---|
169 | iss.read(reinterpret_cast<char*>(&value), sizeof(value));
|
---|
170 | }
|
---|
171 |
|
---|
172 | double doubleValue() override {
|
---|
173 | return value;
|
---|
174 | }
|
---|
175 |
|
---|
176 | void encode(std::ostream &oss) override {
|
---|
177 | encodeType(oss, BSER_REAL);
|
---|
178 | oss.write(reinterpret_cast<char*>(&value), sizeof(value));
|
---|
179 | }
|
---|
180 | };
|
---|
181 |
|
---|
182 | class BSERBoolean : public Value<bool> {
|
---|
183 | public:
|
---|
184 | BSERBoolean(bool value) : Value(value) {}
|
---|
185 | bool boolValue() override { return value; }
|
---|
186 | void encode(std::ostream &oss) override {
|
---|
187 | int8_t t = value == true ? BSER_BOOL_TRUE : BSER_BOOL_FALSE;
|
---|
188 | oss.write(reinterpret_cast<char*>(&t), sizeof(t));
|
---|
189 | }
|
---|
190 | };
|
---|
191 |
|
---|
192 | class BSERNull : public Value<bool> {
|
---|
193 | public:
|
---|
194 | BSERNull() : Value(false) {}
|
---|
195 | void encode(std::ostream &oss) override {
|
---|
196 | encodeType(oss, BSER_NULL);
|
---|
197 | }
|
---|
198 | };
|
---|
199 |
|
---|
200 | std::shared_ptr<BSERArray> decodeTemplate(std::istream &iss) {
|
---|
201 | expectType(iss, BSER_TEMPLATE);
|
---|
202 | auto keys = BSERArray(iss).arrayValue();
|
---|
203 | auto len = BSERInteger(iss).intValue();
|
---|
204 | std::shared_ptr<BSERArray> arr = std::make_shared<BSERArray>();
|
---|
205 | for (int64_t i = 0; i < len; i++) {
|
---|
206 | BSER::Object obj;
|
---|
207 | for (auto it = keys.begin(); it != keys.end(); it++) {
|
---|
208 | if (iss.peek() == 0x0c) {
|
---|
209 | iss.ignore(1);
|
---|
210 | continue;
|
---|
211 | }
|
---|
212 |
|
---|
213 | auto val = BSER(iss);
|
---|
214 | obj.emplace(it->stringValue(), val);
|
---|
215 | }
|
---|
216 | arr->value.push_back(obj);
|
---|
217 | }
|
---|
218 | return arr;
|
---|
219 | }
|
---|
220 |
|
---|
221 | BSER::BSER(std::istream &iss) {
|
---|
222 | BSERType type = decodeType(iss);
|
---|
223 | iss.unget();
|
---|
224 |
|
---|
225 | switch (type) {
|
---|
226 | case BSER_ARRAY:
|
---|
227 | m_ptr = std::make_shared<BSERArray>(iss);
|
---|
228 | break;
|
---|
229 | case BSER_OBJECT:
|
---|
230 | m_ptr = std::make_shared<BSERObject>(iss);
|
---|
231 | break;
|
---|
232 | case BSER_STRING:
|
---|
233 | m_ptr = std::make_shared<BSERString>(iss);
|
---|
234 | break;
|
---|
235 | case BSER_INT8:
|
---|
236 | case BSER_INT16:
|
---|
237 | case BSER_INT32:
|
---|
238 | case BSER_INT64:
|
---|
239 | m_ptr = std::make_shared<BSERInteger>(iss);
|
---|
240 | break;
|
---|
241 | case BSER_REAL:
|
---|
242 | m_ptr = std::make_shared<BSERDouble>(iss);
|
---|
243 | break;
|
---|
244 | case BSER_BOOL_TRUE:
|
---|
245 | iss.ignore(1);
|
---|
246 | m_ptr = std::make_shared<BSERBoolean>(true);
|
---|
247 | break;
|
---|
248 | case BSER_BOOL_FALSE:
|
---|
249 | iss.ignore(1);
|
---|
250 | m_ptr = std::make_shared<BSERBoolean>(false);
|
---|
251 | break;
|
---|
252 | case BSER_NULL:
|
---|
253 | iss.ignore(1);
|
---|
254 | m_ptr = std::make_shared<BSERNull>();
|
---|
255 | break;
|
---|
256 | case BSER_TEMPLATE:
|
---|
257 | m_ptr = decodeTemplate(iss);
|
---|
258 | break;
|
---|
259 | default:
|
---|
260 | throw std::runtime_error("unknown BSER type");
|
---|
261 | }
|
---|
262 | }
|
---|
263 |
|
---|
264 | BSER::BSER() : m_ptr(std::make_shared<BSERNull>()) {}
|
---|
265 | BSER::BSER(BSER::Array value) : m_ptr(std::make_shared<BSERArray>(value)) {}
|
---|
266 | BSER::BSER(BSER::Object value) : m_ptr(std::make_shared<BSERObject>(value)) {}
|
---|
267 | BSER::BSER(const char *value) : m_ptr(std::make_shared<BSERString>(value)) {}
|
---|
268 | BSER::BSER(std::string value) : m_ptr(std::make_shared<BSERString>(value)) {}
|
---|
269 | BSER::BSER(int64_t value) : m_ptr(std::make_shared<BSERInteger>(value)) {}
|
---|
270 | BSER::BSER(double value) : m_ptr(std::make_shared<BSERDouble>(value)) {}
|
---|
271 | BSER::BSER(bool value) : m_ptr(std::make_shared<BSERBoolean>(value)) {}
|
---|
272 |
|
---|
273 | BSER::Array BSER::arrayValue() { return m_ptr->arrayValue(); }
|
---|
274 | BSER::Object BSER::objectValue() { return m_ptr->objectValue(); }
|
---|
275 | std::string BSER::stringValue() { return m_ptr->stringValue(); }
|
---|
276 | int64_t BSER::intValue() { return m_ptr->intValue(); }
|
---|
277 | double BSER::doubleValue() { return m_ptr->doubleValue(); }
|
---|
278 | bool BSER::boolValue() { return m_ptr->boolValue(); }
|
---|
279 | void BSER::encode(std::ostream &oss) {
|
---|
280 | m_ptr->encode(oss);
|
---|
281 | }
|
---|
282 |
|
---|
283 | int64_t BSER::decodeLength(std::istream &iss) {
|
---|
284 | char pdu[2];
|
---|
285 | if (!iss.read(pdu, 2) || pdu[0] != 0 || pdu[1] != 1) {
|
---|
286 | throw std::runtime_error("Invalid BSER");
|
---|
287 | }
|
---|
288 |
|
---|
289 | return BSERInteger(iss).intValue();
|
---|
290 | }
|
---|
291 |
|
---|
292 | std::string BSER::encode() {
|
---|
293 | std::ostringstream oss(std::ios_base::binary);
|
---|
294 | encode(oss);
|
---|
295 |
|
---|
296 | std::ostringstream res(std::ios_base::binary);
|
---|
297 | res.write("\x00\x01", 2);
|
---|
298 |
|
---|
299 | BSERInteger(oss.str().size()).encode(res);
|
---|
300 | res << oss.str();
|
---|
301 | return res.str();
|
---|
302 | }
|
---|