1 // Distributed under the MIT license. Copyright (c) 2010, Ivan Vashchaev
6 // true if character represent a digit
7 #define IS_DIGIT(c) (c >= '0' && c <= '9')
9 // convert string to integer
10 static char *atoi(char *first, char *last, int *out)
20 else if (*first == '+')
27 for (; first != last && IS_DIGIT(*first); ++first)
29 result = 10 * result + (*first - '0');
36 // convert hexadecimal string to unsigned integer
37 static char *hatoui(char *first, char *last, unsigned int *out)
39 unsigned int result = 0;
40 for (; first != last; ++first)
47 else if (*first >= 'a' && *first <= 'f')
49 digit = *first - 'a' + 10;
51 else if (*first >= 'A' && *first <= 'F')
53 digit = *first - 'A' + 10;
59 result = 16 * result + (unsigned int)digit;
66 // convert string to floating point
67 static char *atof(char *first, char *last, float *out)
78 else if (*first == '+')
86 for (; first != last && IS_DIGIT(*first); ++first)
88 result = 10 * result + (float)(*first - '0');
92 if (first != last && *first == '.')
96 float inv_base = 0.1f;
97 for (; first != last && IS_DIGIT(*first); ++first)
99 result += (float)(*first - '0') * inv_base;
104 // result w\o exponent
108 bool exponent_negative = false;
110 if (first != last && (*first == 'e' || *first == 'E'))
116 exponent_negative = true;
119 else if (*first == '+')
124 for (; first != last && IS_DIGIT(*first); ++first)
126 exponent = 10 * exponent + (*first - '0');
132 float power_of_ten = 10;
133 for (; exponent > 1; exponent--)
138 if (exponent_negative)
140 result /= power_of_ten;
144 result *= power_of_ten;
153 static inline json_value *json_alloc(block_allocator *allocator)
155 json_value *value = (json_value *)allocator->malloc(sizeof(json_value));
156 memset(value, 0, sizeof(json_value));
160 static inline void json_append(json_value *lhs, json_value *rhs)
165 lhs->last_child = lhs->last_child->next_sibling = rhs;
169 lhs->first_child = lhs->last_child = rhs;
173 #define ERROR(it, desc)\
176 *error_line = 1 - escaped_newlines;\
177 for (char *c = it; c != source; --c)\
178 if (*c == '\n') ++*error_line;\
181 #define CHECK_TOP() if (!top) {ERROR(it, "Unexpected character");}
183 json_value *json_parse(char *source, char **error_pos, const char **error_desc, int *error_line, block_allocator *allocator)
185 json_value *root = 0;
191 int escaped_newlines = 0;
196 while (*it == '\x20' || *it == '\x9' || *it == '\xD' || *it == '\xA')
209 json_value *object = json_alloc(allocator);
216 object->type = (*it == '{') ? JSON_OBJECT : JSON_ARRAY;
218 // skip open character
224 json_append(top, object);
232 ERROR(it, "Second root. Only one root allowed");
241 if (!top || top->type != ((*it == '}') ? JSON_OBJECT : JSON_ARRAY))
243 ERROR(it, "Mismatch closing brace/bracket");
246 // skip close character
255 if (!top || top->type != JSON_OBJECT)
257 ERROR(it, "Unexpected character");
271 // skip '"' character
278 if ((unsigned char)*it < '\x20')
280 ERROR(first, "Control characters not allowed in strings");
282 else if (*it == '\\')
313 unsigned int codepoint;
314 if (hatoui(it + 2, it + 6, &codepoint) != it + 6)
316 ERROR(it, "Bad unicode codepoint");
319 if (codepoint <= 0x7F)
321 *last = (char)codepoint;
323 else if (codepoint <= 0x7FF)
325 *last++ = (char)(0xC0 | (codepoint >> 6));
326 *last = (char)(0x80 | (codepoint & 0x3F));
328 else if (codepoint <= 0xFFFF)
330 *last++ = (char)(0xE0 | (codepoint >> 12));
331 *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
332 *last = (char)(0x80 | (codepoint & 0x3F));
338 ERROR(first, "Unrecognized escape sequence");
356 if (!name && top->type == JSON_OBJECT)
358 // field name in object
364 json_value *object = json_alloc(allocator);
369 object->type = JSON_STRING;
370 object->string_value = first;
372 json_append(top, object);
383 // new null/bool value
384 json_value *object = json_alloc(allocator);
390 if (it[0] == 'n' && it[1] == 'u' && it[2] == 'l' && it[3] == 'l')
392 object->type = JSON_NULL;
396 else if (it[0] == 't' && it[1] == 'r' && it[2] == 'u' && it[3] == 'e')
398 object->type = JSON_BOOL;
399 object->int_value = 1;
403 else if (it[0] == 'f' && it[1] == 'a' && it[2] == 'l' && it[3] == 's' && it[4] == 'e')
405 object->type = JSON_BOOL;
406 object->int_value = 0;
411 ERROR(it, "Unknown identifier");
414 json_append(top, object);
433 json_value *object = json_alloc(allocator);
438 object->type = JSON_INT;
441 while (*it != '\x20' && *it != '\x9' && *it != '\xD' && *it != '\xA' && *it != ',' && *it != ']' && *it != '}')
443 if (*it == '.' || *it == 'e' || *it == 'E')
445 object->type = JSON_FLOAT;
450 if (object->type == JSON_INT && atoi(first, it, &object->int_value) != it)
452 ERROR(first, "Bad integer number");
455 if (object->type == JSON_FLOAT && atof(first, it, &object->float_value) != it)
457 ERROR(first, "Bad float number");
460 json_append(top, object);
465 ERROR(it, "Unexpected character");
471 ERROR(it, "Not all objects/arrays have been properly closed");