1 // https://github.com/vivkin/gason - pulled January 10, 2016
5 #define JSON_ZONE_SIZE 4096
6 #define JSON_STACK_SIZE 32
8 const char *jsonStrError(int err) {
20 void *JsonAllocator::allocate(size_t size) {
21 size = (size + 7) & ~7;
23 if (head && head->used + size <= JSON_ZONE_SIZE) {
24 char *p = (char *)head + head->used;
29 size_t allocSize = sizeof(Zone) + size;
30 Zone *zone = (Zone *)malloc(allocSize <= JSON_ZONE_SIZE ? JSON_ZONE_SIZE : allocSize);
33 zone->used = allocSize;
34 if (allocSize <= JSON_ZONE_SIZE || head == nullptr) {
38 zone->next = head->next;
41 return (char *)zone + sizeof(Zone);
44 void JsonAllocator::deallocate() {
46 Zone *next = head->next;
52 static inline bool isspace(char c) {
53 return c == ' ' || (c >= '\t' && c <= '\r');
56 static inline bool isdelim(char c) {
57 return c == ',' || c == ':' || c == ']' || c == '}' || isspace(c) || !c;
60 static inline bool isdigit(char c) {
61 return c >= '0' && c <= '9';
64 static inline bool isxdigit(char c) {
65 return (c >= '0' && c <= '9') || ((c & ~' ') >= 'A' && (c & ~' ') <= 'F');
68 static inline int char2int(char c) {
71 return (c & ~' ') - 'A' + 10;
74 static double string2double(char *s, char **endptr) {
81 result = (result * 10) + (*s++ - '0');
89 result += (*s++ - '0') * fraction;
93 if (*s == 'e' || *s == 'E') {
104 unsigned int exponent = 0;
106 exponent = (exponent * 10) + (*s++ - '0');
109 for (; exponent; exponent >>= 1, base *= base)
117 return ch == '-' ? -result : result;
120 static inline JsonNode *insertAfter(JsonNode *tail, JsonNode *node) {
122 return node->next = node;
123 node->next = tail->next;
128 static inline JsonValue listToValue(JsonTag tag, JsonNode *tail) {
130 auto head = tail->next;
131 tail->next = nullptr;
132 return JsonValue(tag, head);
134 return JsonValue(tag, nullptr);
137 int jsonParse(char *s, char **endptr, JsonValue *value, JsonAllocator &allocator) {
138 JsonNode *tails[JSON_STACK_SIZE];
139 JsonTag tags[JSON_STACK_SIZE];
140 char *keys[JSON_STACK_SIZE];
143 bool separator = true;
148 while (isspace(*s)) {
155 if (!isdigit(*s) && *s != '.') {
157 return JSON_BAD_NUMBER;
169 o = JsonValue(string2double(*endptr, &s));
172 return JSON_BAD_NUMBER;
176 o = JsonValue(JSON_STRING, s);
177 for (char *it = s; *s; ++it, ++s) {
204 for (int i = 0; i < 4; ++i) {
205 if (isxdigit(*++s)) {
206 c = c * 16 + char2int(*s);
209 return JSON_BAD_STRING;
214 } else if (c < 0x800) {
215 *it++ = 0xC0 | (c >> 6);
216 *it = 0x80 | (c & 0x3F);
218 *it++ = 0xE0 | (c >> 12);
219 *it++ = 0x80 | ((c >> 6) & 0x3F);
220 *it = 0x80 | (c & 0x3F);
225 return JSON_BAD_STRING;
227 } else if ((unsigned int)c < ' ' || c == '\x7F') {
229 return JSON_BAD_STRING;
230 } else if (c == '"') {
238 return JSON_BAD_STRING;
242 if (!(s[0] == 'r' && s[1] == 'u' && s[2] == 'e' && isdelim(s[3])))
243 return JSON_BAD_IDENTIFIER;
244 o = JsonValue(JSON_TRUE);
248 if (!(s[0] == 'a' && s[1] == 'l' && s[2] == 's' && s[3] == 'e' && isdelim(s[4])))
249 return JSON_BAD_IDENTIFIER;
250 o = JsonValue(JSON_FALSE);
254 if (!(s[0] == 'u' && s[1] == 'l' && s[2] == 'l' && isdelim(s[3])))
255 return JSON_BAD_IDENTIFIER;
256 o = JsonValue(JSON_NULL);
261 return JSON_STACK_UNDERFLOW;
262 if (tags[pos] != JSON_ARRAY)
263 return JSON_MISMATCH_BRACKET;
264 o = listToValue(JSON_ARRAY, tails[pos--]);
268 return JSON_STACK_UNDERFLOW;
269 if (tags[pos] != JSON_OBJECT)
270 return JSON_MISMATCH_BRACKET;
271 if (keys[pos] != nullptr)
272 return JSON_UNEXPECTED_CHARACTER;
273 o = listToValue(JSON_OBJECT, tails[pos--]);
276 if (++pos == JSON_STACK_SIZE)
277 return JSON_STACK_OVERFLOW;
278 tails[pos] = nullptr;
279 tags[pos] = JSON_ARRAY;
284 if (++pos == JSON_STACK_SIZE)
285 return JSON_STACK_OVERFLOW;
286 tails[pos] = nullptr;
287 tags[pos] = JSON_OBJECT;
292 if (separator || keys[pos] == nullptr)
293 return JSON_UNEXPECTED_CHARACTER;
297 if (separator || keys[pos] != nullptr)
298 return JSON_UNEXPECTED_CHARACTER;
304 return JSON_UNEXPECTED_CHARACTER;
315 if (tags[pos] == JSON_OBJECT) {
317 if (o.getTag() != JSON_STRING)
318 return JSON_UNQUOTED_KEY;
319 keys[pos] = o.toString();
322 if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode))) == nullptr)
323 return JSON_ALLOCATION_FAILURE;
324 tails[pos] = insertAfter(tails[pos], node);
325 tails[pos]->key = keys[pos];
328 if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode) - sizeof(char *))) == nullptr)
329 return JSON_ALLOCATION_FAILURE;
330 tails[pos] = insertAfter(tails[pos], node);
332 tails[pos]->value = o;
334 return JSON_BREAKING_BAD;