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