1 /*
2 Copyright (c) 2013-2016, Light Transport Entertainment Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the <organization> nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #ifndef ESON_H_
28 #define ESON_H_
29
30 #include <stdint.h>
31
32 #include <cassert>
33 #include <cstdio>
34 #include <cstdlib>
35
36 #include <map>
37 #include <string>
38 #include <vector>
39
40 namespace eson {
41
42 typedef enum {
43 NULL_TYPE = 0,
44 FLOAT64_TYPE = 1,
45 INT64_TYPE = 2,
46 BOOL_TYPE = 3,
47 STRING_TYPE = 4,
48 ARRAY_TYPE = 5,
49 BINARY_TYPE = 6,
50 OBJECT_TYPE = 7
51 } Type;
52
53 class Value {
54 public:
55 typedef struct {
56 const uint8_t *ptr;
57 int64_t size;
58 } Binary;
59
60 typedef std::vector<Value> Array;
61 typedef std::map<std::string, Value> Object;
62
63 protected:
64 int type_; // Data type
65 int pad0_;
66 mutable uint64_t size_; // Data size
67 mutable bool dirty_;
68
69 // union {
70 bool boolean_;
71 char pad6_[6];
72 int64_t int64_;
73 double float64_;
74 std::string string_;
75 Binary binary_;
76 Array array_;
77 Object object_;
78 //};
79
80 public:
Value()81 Value() : type_(NULL_TYPE), dirty_(true) {}
82
Value(bool b)83 explicit Value(bool b) : type_(BOOL_TYPE), dirty_(false) {
84 boolean_ = b;
85 size_ = 1;
86 }
Value(int64_t i)87 explicit Value(int64_t i) : type_(INT64_TYPE), dirty_(false) {
88 int64_ = i;
89 size_ = 8;
90 }
Value(double n)91 explicit Value(double n) : type_(FLOAT64_TYPE), dirty_(false) {
92 float64_ = n;
93 size_ = 8;
94 }
Value(const std::string & s)95 explicit Value(const std::string &s) : type_(STRING_TYPE), dirty_(false) {
96 string_ = std::string(s);
97 size_ = string_.size();
98 }
Value(const uint8_t * p,uint64_t n)99 explicit Value(const uint8_t *p, uint64_t n)
100 : type_(BINARY_TYPE), dirty_(false) {
101 binary_ = Binary();
102 binary_.ptr = p; // Just save a pointer.
103 binary_.size = static_cast<int64_t>(n);
104 size_ = n;
105 }
Value(const Array & a)106 explicit Value(const Array &a) : type_(ARRAY_TYPE), dirty_(true) {
107 array_ = Array(a);
108 size_ = ComputeArraySize();
109 }
Value(const Object & o)110 explicit Value(const Object &o) : type_(OBJECT_TYPE), dirty_(true) {
111 object_ = Object(o);
112 size_ = ComputeObjectSize();
113 }
114 //~Value() {}
115
116 /// Compute size of array element.
ComputeArraySize()117 uint64_t ComputeArraySize() const {
118 assert(type_ == ARRAY_TYPE);
119
120 assert(array_.size() > 0);
121
122 char base_element_type = array_[0].Type();
123
124 //
125 // Elements in the array must be all same type.
126 //
127
128 uint64_t sum = 0;
129 for (size_t i = 0; i < array_.size(); i++) {
130 char element_type = array_[i].Type();
131 assert(base_element_type == element_type);
132 (void)element_type;
133 sum += array_[i].ComputeSize();
134 }
135 (void)base_element_type;
136
137 return sum + 1 + sizeof(int64_t);
138 }
139
140 /// Compute object size.
ComputeObjectSize()141 uint64_t ComputeObjectSize() const {
142 assert(type_ == OBJECT_TYPE);
143
144 uint64_t object_size = 0;
145
146 for (Object::const_iterator it = object_.begin(); it != object_.end();
147 ++it) {
148 const std::string &key = it->first;
149 uint64_t key_len = key.length() + 1; // + '\0'
150 uint64_t data_len = it->second.ComputeSize();
151 object_size += key_len + data_len + 1; // +1 = tag size.
152 }
153
154 return object_size;
155 }
156
157 /// Compute data size.
ComputeSize()158 uint64_t ComputeSize() const {
159 switch (type_) {
160 case INT64_TYPE:
161 return 8;
162 break;
163 case FLOAT64_TYPE:
164 return 8;
165 break;
166 case STRING_TYPE:
167 return string_.size() + sizeof(int64_t); // N + str data
168 break;
169 case BINARY_TYPE:
170 return size_ + sizeof(int64_t); // N + bin data
171 break;
172 case ARRAY_TYPE:
173 return ComputeArraySize() + sizeof(int64_t); // datalen + N
174 break;
175 case OBJECT_TYPE:
176 return ComputeObjectSize() + sizeof(int64_t); // datalen + N
177 break;
178 default:
179 assert(0);
180 break;
181 }
182 assert(0);
183 return 0; // Never come here.
184 }
185
Size()186 uint64_t Size() const {
187 if (!dirty_) {
188 return size_;
189 } else {
190 // Recompute data size.
191 size_ = ComputeSize();
192 dirty_ = false;
193 return size_;
194 }
195 }
196
Type()197 char Type() const { return static_cast<const char>(type_); }
198
IsBool()199 bool IsBool() const { return (type_ == BOOL_TYPE); }
200
IsInt64()201 bool IsInt64() const { return (type_ == INT64_TYPE); }
202
IsFloat64()203 bool IsFloat64() const { return (type_ == FLOAT64_TYPE); }
204
IsString()205 bool IsString() const { return (type_ == STRING_TYPE); }
206
IsBinary()207 bool IsBinary() const { return (type_ == BINARY_TYPE); }
208
IsArray()209 bool IsArray() const { return (type_ == ARRAY_TYPE); }
210
IsObject()211 bool IsObject() const { return (type_ == OBJECT_TYPE); }
212
213 // Accessor
214 template <typename T>
215 const T &Get() const;
216 template <typename T>
217 T &Get();
218
219 // Lookup value from an array
Get(int64_t idx)220 const Value &Get(int64_t idx) const {
221 static Value &null_value = *(new Value());
222 assert(IsArray());
223 assert(idx >= 0);
224 return (static_cast<uint64_t>(idx) < array_.size())
225 ? array_[static_cast<uint64_t>(idx)]
226 : null_value;
227 }
228
229 // Lookup value from a key-value pair
Get(const std::string & key)230 const Value &Get(const std::string &key) const {
231 static Value &null_value = *(new Value());
232 assert(IsObject());
233 Object::const_iterator it = object_.find(key);
234 return (it != object_.end()) ? it->second : null_value;
235 }
236
ArrayLen()237 size_t ArrayLen() const {
238 if (!IsArray()) return 0;
239 return array_.size();
240 }
241
242 // Valid only for object type.
Has(const std::string & key)243 bool Has(const std::string &key) const {
244 if (!IsObject()) return false;
245 Object::const_iterator it = object_.find(key);
246 return (it != object_.end()) ? true : false;
247 }
248
249 // List keys
Keys()250 std::vector<std::string> Keys() const {
251 std::vector<std::string> keys;
252 if (!IsObject()) return keys; // empty
253
254 for (Object::const_iterator it = object_.begin(); it != object_.end();
255 ++it) {
256 keys.push_back(it->first);
257 }
258
259 return keys;
260 }
261
262 // Serialize data to memory 'p'.
263 // Memory of 'p' must be allocated by app before calling this function.
264 // (size can be obtained by calling 'Size' function.
265 // Return next data location.
266 uint8_t *Serialize(uint8_t *p) const;
267
268 private:
269 static Value null_value();
270 };
271
272 // Alias
273 typedef Value::Array Array;
274 typedef Value::Object Object;
275 typedef Value::Binary Binary;
276
277 #define GET(ctype, var) \
278 template <> \
279 inline const ctype &Value::Get<ctype>() const { \
280 return var; \
281 } \
282 template <> \
283 inline ctype &Value::Get<ctype>() { \
284 return var; \
285 }
286 GET(bool, boolean_)
287 GET(double, float64_)
288 GET(int64_t, int64_)
289 GET(std::string, string_)
290 GET(Binary, binary_)
291 GET(Array, array_)
292 GET(Object, object_)
293 #undef GET
294
295 // Deserialize data from memory 'p'.
296 // Returns error string. Empty if success.
297 std::string Parse(Value &v, const uint8_t *p);
298 std::string Parse(Array &v, const uint8_t *p);
299
300 class ESON {
301 public:
302 ESON();
303 ~ESON();
304
305 /// Load data from a file.
306 bool Load(const char *filename);
307
308 /// Dump data to a file.
309 bool Dump(const char *filename);
310
311 private:
312 uint8_t *data_; /// Pointer to data
313 uint64_t size_; /// Total data size
314
315 bool valid_;
316 };
317
318 } // namespace eson
319
320 #ifdef ESON_IMPLEMENTATION
321 #include <cassert>
322 #include <cstdio>
323 #include <cstdlib>
324 #include <cstring>
325 #include <sstream>
326
327 #ifdef _WIN32
328 #include <Windows.h> // File mapping
329 #else
330 #include <fcntl.h>
331 #include <sys/mman.h>
332 #include <sys/stat.h>
333 #include <unistd.h>
334 #endif
335
336 namespace eson {
337
Serialize(uint8_t * p)338 uint8_t *Value::Serialize(uint8_t *p) const {
339 uint8_t *ptr = p;
340 switch (type_) {
341 case FLOAT64_TYPE:
342 memcpy(ptr, &float64_, sizeof(double));
343 ptr += sizeof(double);
344 break;
345 case INT64_TYPE: {
346 // (*(reinterpret_cast<int64_t *>(ptr))) = int64_;
347 memcpy(ptr, &int64_, sizeof(int64_t));
348 ptr += sizeof(int64_t);
349 } break;
350 case STRING_TYPE: {
351 // len(64bit) + string
352 // (*(reinterpret_cast<int64_t *>(ptr))) = size_;
353 memcpy(ptr, &size_, sizeof(int64_t));
354 ptr += sizeof(int64_t);
355 memcpy(ptr, string_.c_str(), static_cast<size_t>(size_));
356 ptr += size_;
357 } break;
358 case BINARY_TYPE: {
359 // len(64bit) + bindata
360 // (*(reinterpret_cast<int64_t *>(ptr))) = size_;
361 memcpy(ptr, &size_, sizeof(int64_t));
362 ptr += sizeof(int64_t);
363 memcpy(ptr, binary_.ptr, static_cast<size_t>(size_));
364 ptr += size_;
365 } break;
366 case OBJECT_TYPE: {
367 // (*(reinterpret_cast<int64_t *>(ptr))) = size_;
368 memcpy(ptr, &size_, sizeof(int64_t));
369 ptr += sizeof(int64_t);
370
371 // Serialize key-value pairs.
372 for (Object::const_iterator it = object_.begin(); it != object_.end();
373 ++it) {
374 // Emit type tag.
375 char ty = static_cast<char>(it->second.type_);
376 (*(reinterpret_cast<char *>(ptr))) = ty;
377 ptr++;
378
379 // Emit key
380 const std::string &key = it->first;
381 memcpy(ptr, key.c_str(), key.size());
382 ptr += key.size();
383 (*(reinterpret_cast<char *>(ptr))) = '\0'; // null terminate
384 ptr++;
385
386 // Emit element
387 ptr = it->second.Serialize(ptr);
388 }
389 } break;
390 case ARRAY_TYPE: {
391 // (*(reinterpret_cast<int64_t *>(ptr))) = size_;
392 memcpy(ptr, &size_, sizeof(int64_t));
393 ptr += sizeof(int64_t);
394
395 char ty = static_cast<char>(type_);
396 (*(reinterpret_cast<char *>(ptr))) = ty;
397 ptr++;
398
399 // (*(reinterpret_cast<int64_t *>(ptr))) = array_.size();
400 uint64_t arraySize = array_.size();
401 memcpy(ptr, &arraySize, sizeof(int64_t));
402 ptr += sizeof(int64_t);
403
404 for (size_t i = 0; i < array_.size(); i++) {
405 ptr = array_[i].Serialize(ptr);
406 }
407 } break;
408 default:
409 assert(0);
410 break;
411 }
412
413 return ptr;
414 }
415
416 // Forward decl.
417 static const uint8_t *ParseElement(std::stringstream &err, Object &o,
418 const uint8_t *p);
419
ReadKey(std::string & key,const uint8_t * p)420 static const uint8_t *ReadKey(std::string &key, const uint8_t *p) {
421 key = std::string(reinterpret_cast<const char *>(p));
422
423 p += key.length() + 1; // + '\0'
424
425 return p;
426 }
427
ReadFloat64(double & v,const uint8_t * p)428 static const uint8_t *ReadFloat64(double &v, const uint8_t *p) {
429 double val = 0.0;
430 memcpy(&val, p, sizeof(double));
431 v = val;
432 p += sizeof(double);
433
434 return p;
435 }
436
ReadInt64(int64_t & v,const uint8_t * p)437 static const uint8_t *ReadInt64(int64_t &v, const uint8_t *p) {
438 int64_t val = 0;
439 memcpy(&val, p, sizeof(int64_t));
440 v = val;
441 p += sizeof(int64_t);
442
443 return p;
444 }
445
ReadString(std::string & s,const uint8_t * p)446 static const uint8_t *ReadString(std::string &s, const uint8_t *p) {
447 // N + string data.
448 int64_t val;
449 memcpy(&val, p, sizeof(int64_t));
450 int64_t n = val;
451 p += sizeof(int64_t);
452
453 assert(n >= 0);
454
455 s = std::string(reinterpret_cast<const char *>(p), static_cast<size_t>(n));
456 p += n;
457
458 return p;
459 }
460
ReadBinary(const uint8_t * & b,int64_t & n,const uint8_t * p)461 static const uint8_t *ReadBinary(const uint8_t *&b, int64_t &n,
462 const uint8_t *p) {
463 // N + bin data.
464 int64_t val;
465 memcpy(&val, p, sizeof(int64_t));
466
467 n = val;
468 p += sizeof(int64_t);
469
470 assert(n >= 0);
471
472 // Just returns pointer address.
473 b = p;
474 p += n;
475
476 return p;
477 }
478
ReadObject(Object & o,const uint8_t * p)479 static const uint8_t *ReadObject(Object &o, const uint8_t *p) {
480 // N + object data.
481 int64_t val;
482 memcpy(&val, p, sizeof(int64_t));
483 int64_t n = val;
484 p += sizeof(int64_t);
485
486 assert(n >= 0);
487 (void)n;
488
489 std::stringstream ss;
490 const uint8_t *ptr = ParseElement(ss, o, p);
491
492 return ptr;
493 }
494
ParseElement(std::stringstream & err,Object & o,const uint8_t * p)495 static const uint8_t *ParseElement(std::stringstream &err, Object &o,
496 const uint8_t *p) {
497 const uint8_t *ptr = p;
498 (void)err;
499
500 // Read tag;
501 Type type = static_cast<Type>(*(reinterpret_cast<const char *>(ptr)));
502 ptr++;
503
504 std::string key;
505 ptr = ReadKey(key, ptr);
506
507 switch (type) {
508 case FLOAT64_TYPE: {
509 double val;
510 ptr = ReadFloat64(val, ptr);
511 o[key] = Value(val);
512 } break;
513 case INT64_TYPE: {
514 int64_t val;
515 ptr = ReadInt64(val, ptr);
516 o[key] = Value(val);
517 } break;
518 case STRING_TYPE: {
519 std::string str;
520 ptr = ReadString(str, ptr);
521 o[key] = Value(str);
522 } break;
523 case BINARY_TYPE: {
524 const uint8_t *bin_ptr;
525 int64_t bin_size;
526 ptr = ReadBinary(bin_ptr, bin_size, ptr);
527 o[key] = Value(bin_ptr, static_cast<uint64_t>(bin_size));
528 } break;
529 case OBJECT_TYPE: {
530 Object obj;
531 ptr = ReadObject(obj, ptr);
532
533 o[key] = Value(obj);
534 } break;
535 case NULL_TYPE: {
536 } break;
537 case BOOL_TYPE: {
538 // @todo
539 assert(0);
540 } break;
541 case ARRAY_TYPE: {
542 // @todo
543 assert(0);
544 } break;
545 }
546
547 return ptr;
548 }
549
ParseElement(std::stringstream & err,Value & v,const uint8_t * ptr)550 static const uint8_t *ParseElement(std::stringstream &err, Value &v,
551 const uint8_t *ptr) {
552 const uint8_t *p = ptr;
553 // Read total size.
554 int64_t val = 0;
555 memcpy(&val, ptr, sizeof(int64_t));
556 int64_t sz = val;
557 ptr += sizeof(int64_t);
558 assert(sz > 0);
559
560 Object obj;
561
562 int64_t read_size = 0;
563 while (read_size < sz) {
564 ptr = ParseElement(err, obj, ptr);
565 read_size = ptr - p;
566 }
567 v = Value(obj);
568 return ptr;
569 }
570
ParseElement(std::stringstream & err,Array & o,const uint8_t * p)571 static const uint8_t *ParseElement(std::stringstream &err, Array &o,
572 const uint8_t *p) {
573 const uint8_t *ptr = p;
574
575 // Read tag;
576 Type type = static_cast<Type>(*(reinterpret_cast<const char *>(ptr)));
577 ptr++;
578
579 std::string key;
580 if (type != ARRAY_TYPE) ptr = ReadKey(key, ptr);
581
582 assert(type == ARRAY_TYPE);
583
584 int64_t nElems;
585 ptr = ReadInt64(nElems, ptr);
586
587 for (size_t i = 0; i < static_cast<size_t>(nElems); i++) {
588 Value value;
589 ptr = ParseElement(err, value, ptr);
590 o.push_back(value);
591 }
592
593 return ptr;
594 }
595
Parse(Value & v,const uint8_t * p)596 std::string Parse(Value &v, const uint8_t *p) {
597 std::stringstream err;
598
599 const uint8_t *ptr = p;
600
601 //
602 // == toplevel element
603 //
604
605 // Read total size.
606 int64_t val = 0;
607 memcpy(&val, ptr, sizeof(int64_t));
608 int64_t sz = val;
609 ptr += sizeof(int64_t);
610 assert(sz > 0);
611
612 Object obj;
613
614 int64_t read_size = 0;
615 while (read_size < sz) {
616 ptr = ParseElement(err, obj, ptr);
617 read_size = ptr - p;
618 }
619
620 v = Value(obj);
621
622 return err.str();
623 }
624
Parse(Array & v,const uint8_t * p)625 std::string Parse(Array &v, const uint8_t *p) {
626 std::stringstream err;
627
628 const uint8_t *ptr = p;
629
630 //
631 // == toplevel element
632 //
633
634 // Read total size.
635 int64_t val = 0;
636 memcpy(&val, ptr, sizeof(int64_t));
637 int64_t sz = val;
638 ptr += sizeof(int64_t);
639 assert(sz > 0);
640
641 int64_t read_size = 0;
642 while (read_size < sz) {
643 ptr = ParseElement(err, v, ptr);
644 read_size = ptr - p;
645 }
646
647 return err.str();
648 }
649
650 } // namespace eson
651 #endif
652
653 #endif // ESON_H_
654