EG version upgrade to 1.3
[ealt-edge.git] / example-apps / PDD / pcb-defect-detection / data / lib_coco / common / gason.h
1 // https://github.com/vivkin/gason - pulled January 10, 2016
2 #pragma once
3
4 #include <stdint.h>
5 #include <stddef.h>
6 #include <assert.h>
7
8 enum JsonTag {
9     JSON_NUMBER = 0,
10     JSON_STRING,
11     JSON_ARRAY,
12     JSON_OBJECT,
13     JSON_TRUE,
14     JSON_FALSE,
15     JSON_NULL = 0xF
16 };
17
18 struct JsonNode;
19
20 #define JSON_VALUE_PAYLOAD_MASK 0x00007FFFFFFFFFFFULL
21 #define JSON_VALUE_NAN_MASK 0x7FF8000000000000ULL
22 #define JSON_VALUE_TAG_MASK 0xF
23 #define JSON_VALUE_TAG_SHIFT 47
24
25 union JsonValue {
26     uint64_t ival;
27     double fval;
28
29     JsonValue(double x)
30         : fval(x) {
31     }
32     JsonValue(JsonTag tag = JSON_NULL, void *payload = nullptr) {
33         assert((uintptr_t)payload <= JSON_VALUE_PAYLOAD_MASK);
34         ival = JSON_VALUE_NAN_MASK | ((uint64_t)tag << JSON_VALUE_TAG_SHIFT) | (uintptr_t)payload;
35     }
36     bool isDouble() const {
37         return (int64_t)ival <= (int64_t)JSON_VALUE_NAN_MASK;
38     }
39     JsonTag getTag() const {
40         return isDouble() ? JSON_NUMBER : JsonTag((ival >> JSON_VALUE_TAG_SHIFT) & JSON_VALUE_TAG_MASK);
41     }
42     uint64_t getPayload() const {
43         assert(!isDouble());
44         return ival & JSON_VALUE_PAYLOAD_MASK;
45     }
46     double toNumber() const {
47         assert(getTag() == JSON_NUMBER);
48         return fval;
49     }
50     char *toString() const {
51         assert(getTag() == JSON_STRING);
52         return (char *)getPayload();
53     }
54     JsonNode *toNode() const {
55         assert(getTag() == JSON_ARRAY || getTag() == JSON_OBJECT);
56         return (JsonNode *)getPayload();
57     }
58 };
59
60 struct JsonNode {
61     JsonValue value;
62     JsonNode *next;
63     char *key;
64 };
65
66 struct JsonIterator {
67     JsonNode *p;
68
69     void operator++() {
70         p = p->next;
71     }
72     bool operator!=(const JsonIterator &x) const {
73         return p != x.p;
74     }
75     JsonNode *operator*() const {
76         return p;
77     }
78     JsonNode *operator->() const {
79         return p;
80     }
81 };
82
83 inline JsonIterator begin(JsonValue o) {
84     return JsonIterator{o.toNode()};
85 }
86 inline JsonIterator end(JsonValue) {
87     return JsonIterator{nullptr};
88 }
89
90 #define JSON_ERRNO_MAP(XX)                           \
91     XX(OK, "ok")                                     \
92     XX(BAD_NUMBER, "bad number")                     \
93     XX(BAD_STRING, "bad string")                     \
94     XX(BAD_IDENTIFIER, "bad identifier")             \
95     XX(STACK_OVERFLOW, "stack overflow")             \
96     XX(STACK_UNDERFLOW, "stack underflow")           \
97     XX(MISMATCH_BRACKET, "mismatch bracket")         \
98     XX(UNEXPECTED_CHARACTER, "unexpected character") \
99     XX(UNQUOTED_KEY, "unquoted key")                 \
100     XX(BREAKING_BAD, "breaking bad")                 \
101     XX(ALLOCATION_FAILURE, "allocation failure")
102
103 enum JsonErrno {
104 #define XX(no, str) JSON_##no,
105     JSON_ERRNO_MAP(XX)
106 #undef XX
107 };
108
109 const char *jsonStrError(int err);
110
111 class JsonAllocator {
112     struct Zone {
113         Zone *next;
114         size_t used;
115     } *head = nullptr;
116
117 public:
118     JsonAllocator() = default;
119     JsonAllocator(const JsonAllocator &) = delete;
120     JsonAllocator &operator=(const JsonAllocator &) = delete;
121     JsonAllocator(JsonAllocator &&x) : head(x.head) {
122         x.head = nullptr;
123     }
124     JsonAllocator &operator=(JsonAllocator &&x) {
125         head = x.head;
126         x.head = nullptr;
127         return *this;
128     }
129     ~JsonAllocator() {
130         deallocate();
131     }
132     void *allocate(size_t size);
133     void deallocate();
134 };
135
136 int jsonParse(char *str, char **endptr, JsonValue *value, JsonAllocator &allocator);