| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381 |
- /*
- Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
- All rights reserved.
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #include "json.h"
- #include <assert.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define out_of_memory() do { \
- fprintf(stderr, "Out of memory.\n"); \
- exit(EXIT_FAILURE); \
- } while (0)
- /* Sadly, strdup is not portable. */
- static char *json_strdup(const char *str)
- {
- char *ret = (char*) malloc(strlen(str) + 1);
- if (ret == NULL)
- out_of_memory();
- strcpy(ret, str);
- return ret;
- }
- /* String buffer */
- typedef struct
- {
- char *cur;
- char *end;
- char *start;
- } SB;
- static void sb_init(SB *sb)
- {
- sb->start = (char*) malloc(17);
- if (sb->start == NULL)
- out_of_memory();
- sb->cur = sb->start;
- sb->end = sb->start + 16;
- }
- /* sb and need may be evaluated multiple times. */
- #define sb_need(sb, need) do { \
- if ((sb)->end - (sb)->cur < (need)) \
- sb_grow(sb, need); \
- } while (0)
- static void sb_grow(SB *sb, int need)
- {
- size_t length = sb->cur - sb->start;
- size_t alloc = sb->end - sb->start;
-
- do {
- alloc *= 2;
- } while (alloc < length + need);
-
- sb->start = (char*) realloc(sb->start, alloc + 1);
- if (sb->start == NULL)
- out_of_memory();
- sb->cur = sb->start + length;
- sb->end = sb->start + alloc;
- }
- static void sb_put(SB *sb, const char *bytes, int count)
- {
- sb_need(sb, count);
- memcpy(sb->cur, bytes, count);
- sb->cur += count;
- }
- #define sb_putc(sb, c) do { \
- if ((sb)->cur >= (sb)->end) \
- sb_grow(sb, 1); \
- *(sb)->cur++ = (c); \
- } while (0)
- static void sb_puts(SB *sb, const char *str)
- {
- sb_put(sb, str, strlen(str));
- }
- static char *sb_finish(SB *sb)
- {
- *sb->cur = 0;
- assert(sb->start <= sb->cur && strlen(sb->start) == (size_t)(sb->cur - sb->start));
- return sb->start;
- }
- static void sb_free(SB *sb)
- {
- free(sb->start);
- }
- /*
- * Unicode helper functions
- *
- * These are taken from the ccan/charset module and customized a bit.
- * Putting them here means the compiler can (choose to) inline them,
- * and it keeps ccan/json from having a dependency.
- */
- /*
- * Type for Unicode codepoints.
- * We need our own because wchar_t might be 16 bits.
- */
- typedef uint32_t uchar_t;
- /*
- * Validate a single UTF-8 character starting at @s.
- * The string must be null-terminated.
- *
- * If it's valid, return its length (1 thru 4).
- * If it's invalid or clipped, return 0.
- *
- * This function implements the syntax given in RFC3629, which is
- * the same as that given in The Unicode Standard, Version 6.0.
- *
- * It has the following properties:
- *
- * * All codepoints U+0000..U+10FFFF may be encoded,
- * except for U+D800..U+DFFF, which are reserved
- * for UTF-16 surrogate pair encoding.
- * * UTF-8 byte sequences longer than 4 bytes are not permitted,
- * as they exceed the range of Unicode.
- * * The sixty-six Unicode "non-characters" are permitted
- * (namely, U+FDD0..U+FDEF, U+xxFFFE, and U+xxFFFF).
- */
- static int utf8_validate_cz(const char *s)
- {
- unsigned char c = *s++;
-
- if (c <= 0x7F) { /* 00..7F */
- return 1;
- } else if (c <= 0xC1) { /* 80..C1 */
- /* Disallow overlong 2-byte sequence. */
- return 0;
- } else if (c <= 0xDF) { /* C2..DF */
- /* Make sure subsequent byte is in the range 0x80..0xBF. */
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
-
- return 2;
- } else if (c <= 0xEF) { /* E0..EF */
- /* Disallow overlong 3-byte sequence. */
- if (c == 0xE0 && (unsigned char)*s < 0xA0)
- return 0;
-
- /* Disallow U+D800..U+DFFF. */
- if (c == 0xED && (unsigned char)*s > 0x9F)
- return 0;
-
- /* Make sure subsequent bytes are in the range 0x80..0xBF. */
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
-
- return 3;
- } else if (c <= 0xF4) { /* F0..F4 */
- /* Disallow overlong 4-byte sequence. */
- if (c == 0xF0 && (unsigned char)*s < 0x90)
- return 0;
-
- /* Disallow codepoints beyond U+10FFFF. */
- if (c == 0xF4 && (unsigned char)*s > 0x8F)
- return 0;
-
- /* Make sure subsequent bytes are in the range 0x80..0xBF. */
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
-
- return 4;
- } else { /* F5..FF */
- return 0;
- }
- }
- /* Validate a null-terminated UTF-8 string. */
- static bool utf8_validate(const char *s)
- {
- int len;
-
- for (; *s != 0; s += len) {
- len = utf8_validate_cz(s);
- if (len == 0)
- return false;
- }
-
- return true;
- }
- /*
- * Read a single UTF-8 character starting at @s,
- * returning the length, in bytes, of the character read.
- *
- * This function assumes input is valid UTF-8,
- * and that there are enough characters in front of @s.
- */
- static int utf8_read_char(const char *s, uchar_t *out)
- {
- const unsigned char *c = (const unsigned char*) s;
-
- assert(utf8_validate_cz(s));
- if (c[0] <= 0x7F) {
- /* 00..7F */
- *out = c[0];
- return 1;
- } else if (c[0] <= 0xDF) {
- /* C2..DF (unless input is invalid) */
- *out = ((uchar_t)c[0] & 0x1F) << 6 |
- ((uchar_t)c[1] & 0x3F);
- return 2;
- } else if (c[0] <= 0xEF) {
- /* E0..EF */
- *out = ((uchar_t)c[0] & 0xF) << 12 |
- ((uchar_t)c[1] & 0x3F) << 6 |
- ((uchar_t)c[2] & 0x3F);
- return 3;
- } else {
- /* F0..F4 (unless input is invalid) */
- *out = ((uchar_t)c[0] & 0x7) << 18 |
- ((uchar_t)c[1] & 0x3F) << 12 |
- ((uchar_t)c[2] & 0x3F) << 6 |
- ((uchar_t)c[3] & 0x3F);
- return 4;
- }
- }
- /*
- * Write a single UTF-8 character to @s,
- * returning the length, in bytes, of the character written.
- *
- * @unicode must be U+0000..U+10FFFF, but not U+D800..U+DFFF.
- *
- * This function will write up to 4 bytes to @out.
- */
- static int utf8_write_char(uchar_t unicode, char *out)
- {
- unsigned char *o = (unsigned char*) out;
-
- assert(unicode <= 0x10FFFF && !(unicode >= 0xD800 && unicode <= 0xDFFF));
- if (unicode <= 0x7F) {
- /* U+0000..U+007F */
- *o++ = unicode;
- return 1;
- } else if (unicode <= 0x7FF) {
- /* U+0080..U+07FF */
- *o++ = 0xC0 | unicode >> 6;
- *o++ = 0x80 | (unicode & 0x3F);
- return 2;
- } else if (unicode <= 0xFFFF) {
- /* U+0800..U+FFFF */
- *o++ = 0xE0 | unicode >> 12;
- *o++ = 0x80 | (unicode >> 6 & 0x3F);
- *o++ = 0x80 | (unicode & 0x3F);
- return 3;
- } else {
- /* U+10000..U+10FFFF */
- *o++ = 0xF0 | unicode >> 18;
- *o++ = 0x80 | (unicode >> 12 & 0x3F);
- *o++ = 0x80 | (unicode >> 6 & 0x3F);
- *o++ = 0x80 | (unicode & 0x3F);
- return 4;
- }
- }
- /*
- * Compute the Unicode codepoint of a UTF-16 surrogate pair.
- *
- * @uc should be 0xD800..0xDBFF, and @lc should be 0xDC00..0xDFFF.
- * If they aren't, this function returns false.
- */
- static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uchar_t *unicode)
- {
- if (uc >= 0xD800 && uc <= 0xDBFF && lc >= 0xDC00 && lc <= 0xDFFF) {
- *unicode = 0x10000 + ((((uchar_t)uc & 0x3FF) << 10) | (lc & 0x3FF));
- return true;
- } else {
- return false;
- }
- }
- /*
- * Construct a UTF-16 surrogate pair given a Unicode codepoint.
- *
- * @unicode must be U+10000..U+10FFFF.
- */
- static void to_surrogate_pair(uchar_t unicode, uint16_t *uc, uint16_t *lc)
- {
- uchar_t n;
-
- assert(unicode >= 0x10000 && unicode <= 0x10FFFF);
-
- n = unicode - 0x10000;
- *uc = ((n >> 10) & 0x3FF) | 0xD800;
- *lc = (n & 0x3FF) | 0xDC00;
- }
- #define is_space(c) ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
- #define is_digit(c) ((c) >= '0' && (c) <= '9')
- static bool parse_value (const char **sp, JsonNode **out);
- static bool parse_string (const char **sp, char **out);
- static bool parse_number (const char **sp, double *out);
- static bool parse_array (const char **sp, JsonNode **out);
- static bool parse_object (const char **sp, JsonNode **out);
- static bool parse_hex16 (const char **sp, uint16_t *out);
- static bool expect_literal (const char **sp, const char *str);
- static void skip_space (const char **sp);
- static void emit_value (SB *out, const JsonNode *node);
- static void emit_value_indented (SB *out, const JsonNode *node, const char *space, int indent_level);
- static void emit_string (SB *out, const char *str);
- static void emit_number (SB *out, double num);
- static void emit_array (SB *out, const JsonNode *array);
- static void emit_array_indented (SB *out, const JsonNode *array, const char *space, int indent_level);
- static void emit_object (SB *out, const JsonNode *object);
- static void emit_object_indented (SB *out, const JsonNode *object, const char *space, int indent_level);
- static int write_hex16(char *out, uint16_t val);
- static JsonNode *mknode(JsonTag tag);
- static void append_node(JsonNode *parent, JsonNode *child);
- static void prepend_node(JsonNode *parent, JsonNode *child);
- static void append_member(JsonNode *object, char *key, JsonNode *value);
- /* Assertion-friendly validity checks */
- static bool tag_is_valid(unsigned int tag);
- static bool number_is_valid(const char *num);
- JsonNode *json_decode(const char *json)
- {
- const char *s = json;
- JsonNode *ret;
-
- skip_space(&s);
- if (!parse_value(&s, &ret))
- return NULL;
-
- skip_space(&s);
- if (*s != 0) {
- json_delete(ret);
- return NULL;
- }
-
- return ret;
- }
- char *json_encode(const JsonNode *node)
- {
- return json_stringify(node, NULL);
- }
- char *json_encode_string(const char *str)
- {
- SB sb;
- sb_init(&sb);
-
- emit_string(&sb, str);
-
- return sb_finish(&sb);
- }
- char *json_stringify(const JsonNode *node, const char *space)
- {
- SB sb;
- sb_init(&sb);
-
- if (space != NULL)
- emit_value_indented(&sb, node, space, 0);
- else
- emit_value(&sb, node);
-
- return sb_finish(&sb);
- }
- void json_delete(JsonNode *node)
- {
- if (node != NULL) {
- json_remove_from_parent(node);
-
- switch (node->tag) {
- case JSON_STRING:
- free(node->string_);
- break;
- case JSON_ARRAY:
- case JSON_OBJECT:
- {
- JsonNode *child, *next;
- for (child = node->children.head; child != NULL; child = next) {
- next = child->next;
- json_delete(child);
- }
- break;
- }
- default:;
- }
-
- free(node);
- }
- }
- bool json_validate(const char *json)
- {
- const char *s = json;
-
- skip_space(&s);
- if (!parse_value(&s, NULL))
- return false;
-
- skip_space(&s);
- if (*s != 0)
- return false;
-
- return true;
- }
- JsonNode *json_find_element(JsonNode *array, int index)
- {
- JsonNode *element;
- int i = 0;
-
- if (array == NULL || array->tag != JSON_ARRAY)
- return NULL;
-
- json_foreach(element, array) {
- if (i == index)
- return element;
- i++;
- }
-
- return NULL;
- }
- JsonNode *json_find_member(JsonNode *object, const char *name)
- {
- JsonNode *member;
-
- if (object == NULL || object->tag != JSON_OBJECT)
- return NULL;
-
- json_foreach(member, object)
- if (strcmp(member->key, name) == 0)
- return member;
-
- return NULL;
- }
- JsonNode *json_first_child(const JsonNode *node)
- {
- if (node != NULL && (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT))
- return node->children.head;
- return NULL;
- }
- static JsonNode *mknode(JsonTag tag)
- {
- JsonNode *ret = (JsonNode*) calloc(1, sizeof(JsonNode));
- if (ret == NULL)
- out_of_memory();
- ret->tag = tag;
- return ret;
- }
- JsonNode *json_mknull(void)
- {
- return mknode(JSON_NULL);
- }
- JsonNode *json_mkbool(bool b)
- {
- JsonNode *ret = mknode(JSON_BOOL);
- ret->bool_ = b;
- return ret;
- }
- static JsonNode *mkstring(char *s)
- {
- JsonNode *ret = mknode(JSON_STRING);
- ret->string_ = s;
- return ret;
- }
- JsonNode *json_mkstring(const char *s)
- {
- return mkstring(json_strdup(s));
- }
- JsonNode *json_mknumber(double n)
- {
- JsonNode *node = mknode(JSON_NUMBER);
- node->number_ = n;
- return node;
- }
- JsonNode *json_mkarray(void)
- {
- return mknode(JSON_ARRAY);
- }
- JsonNode *json_mkobject(void)
- {
- return mknode(JSON_OBJECT);
- }
- static void append_node(JsonNode *parent, JsonNode *child)
- {
- child->parent = parent;
- child->prev = parent->children.tail;
- child->next = NULL;
-
- if (parent->children.tail != NULL)
- parent->children.tail->next = child;
- else
- parent->children.head = child;
- parent->children.tail = child;
- }
- static void prepend_node(JsonNode *parent, JsonNode *child)
- {
- child->parent = parent;
- child->prev = NULL;
- child->next = parent->children.head;
-
- if (parent->children.head != NULL)
- parent->children.head->prev = child;
- else
- parent->children.tail = child;
- parent->children.head = child;
- }
- static void append_member(JsonNode *object, char *key, JsonNode *value)
- {
- value->key = key;
- append_node(object, value);
- }
- void json_append_element(JsonNode *array, JsonNode *element)
- {
- assert(array->tag == JSON_ARRAY);
- assert(element->parent == NULL);
-
- append_node(array, element);
- }
- void json_prepend_element(JsonNode *array, JsonNode *element)
- {
- assert(array->tag == JSON_ARRAY);
- assert(element->parent == NULL);
-
- prepend_node(array, element);
- }
- void json_append_member(JsonNode *object, const char *key, JsonNode *value)
- {
- assert(object->tag == JSON_OBJECT);
- assert(value->parent == NULL);
-
- append_member(object, json_strdup(key), value);
- }
- void json_prepend_member(JsonNode *object, const char *key, JsonNode *value)
- {
- assert(object->tag == JSON_OBJECT);
- assert(value->parent == NULL);
-
- value->key = json_strdup(key);
- prepend_node(object, value);
- }
- void json_remove_from_parent(JsonNode *node)
- {
- JsonNode *parent = node->parent;
-
- if (parent != NULL) {
- if (node->prev != NULL)
- node->prev->next = node->next;
- else
- parent->children.head = node->next;
- if (node->next != NULL)
- node->next->prev = node->prev;
- else
- parent->children.tail = node->prev;
-
- free(node->key);
-
- node->parent = NULL;
- node->prev = node->next = NULL;
- node->key = NULL;
- }
- }
- static bool parse_value(const char **sp, JsonNode **out)
- {
- const char *s = *sp;
-
- switch (*s) {
- case 'n':
- if (expect_literal(&s, "null")) {
- if (out)
- *out = json_mknull();
- *sp = s;
- return true;
- }
- return false;
-
- case 'f':
- if (expect_literal(&s, "false")) {
- if (out)
- *out = json_mkbool(false);
- *sp = s;
- return true;
- }
- return false;
-
- case 't':
- if (expect_literal(&s, "true")) {
- if (out)
- *out = json_mkbool(true);
- *sp = s;
- return true;
- }
- return false;
-
- case '"': {
- char *str;
- if (parse_string(&s, out ? &str : NULL)) {
- if (out)
- *out = mkstring(str);
- *sp = s;
- return true;
- }
- return false;
- }
-
- case '[':
- if (parse_array(&s, out)) {
- *sp = s;
- return true;
- }
- return false;
-
- case '{':
- if (parse_object(&s, out)) {
- *sp = s;
- return true;
- }
- return false;
-
- default: {
- double num;
- if (parse_number(&s, out ? &num : NULL)) {
- if (out)
- *out = json_mknumber(num);
- *sp = s;
- return true;
- }
- return false;
- }
- }
- }
- static bool parse_array(const char **sp, JsonNode **out)
- {
- const char *s = *sp;
- JsonNode *ret = out ? json_mkarray() : NULL;
- JsonNode *element;
-
- if (*s++ != '[')
- goto failure;
- skip_space(&s);
-
- if (*s == ']') {
- s++;
- goto success;
- }
-
- for (;;) {
- if (!parse_value(&s, out ? &element : NULL))
- goto failure;
- skip_space(&s);
-
- if (out)
- json_append_element(ret, element);
-
- if (*s == ']') {
- s++;
- goto success;
- }
-
- if (*s++ != ',')
- goto failure;
- skip_space(&s);
- }
-
- success:
- *sp = s;
- if (out)
- *out = ret;
- return true;
- failure:
- json_delete(ret);
- return false;
- }
- static bool parse_object(const char **sp, JsonNode **out)
- {
- const char *s = *sp;
- JsonNode *ret = out ? json_mkobject() : NULL;
- char *key;
- JsonNode *value;
-
- if (*s++ != '{')
- goto failure;
- skip_space(&s);
-
- if (*s == '}') {
- s++;
- goto success;
- }
-
- for (;;) {
- if (!parse_string(&s, out ? &key : NULL))
- goto failure;
- skip_space(&s);
-
- if (*s++ != ':')
- goto failure_free_key;
- skip_space(&s);
-
- if (!parse_value(&s, out ? &value : NULL))
- goto failure_free_key;
- skip_space(&s);
-
- if (out)
- append_member(ret, key, value);
-
- if (*s == '}') {
- s++;
- goto success;
- }
-
- if (*s++ != ',')
- goto failure;
- skip_space(&s);
- }
-
- success:
- *sp = s;
- if (out)
- *out = ret;
- return true;
- failure_free_key:
- if (out)
- free(key);
- failure:
- json_delete(ret);
- return false;
- }
- bool parse_string(const char **sp, char **out)
- {
- const char *s = *sp;
- SB sb;
- char throwaway_buffer[4];
- /* enough space for a UTF-8 character */
- char *b;
-
- if (*s++ != '"')
- return false;
-
- if (out) {
- sb_init(&sb);
- sb_need(&sb, 4);
- b = sb.cur;
- } else {
- b = throwaway_buffer;
- }
-
- while (*s != '"') {
- unsigned char c = *s++;
-
- /* Parse next character, and write it to b. */
- if (c == '\\') {
- c = *s++;
- switch (c) {
- case '"':
- case '\\':
- case '/':
- *b++ = c;
- break;
- case 'b':
- *b++ = '\b';
- break;
- case 'f':
- *b++ = '\f';
- break;
- case 'n':
- *b++ = '\n';
- break;
- case 'r':
- *b++ = '\r';
- break;
- case 't':
- *b++ = '\t';
- break;
- case 'u':
- {
- uint16_t uc, lc;
- uchar_t unicode;
-
- if (!parse_hex16(&s, &uc))
- goto failed;
-
- if (uc >= 0xD800 && uc <= 0xDFFF) {
- /* Handle UTF-16 surrogate pair. */
- if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc))
- goto failed; /* Incomplete surrogate pair. */
- if (!from_surrogate_pair(uc, lc, &unicode))
- goto failed; /* Invalid surrogate pair. */
- } else if (uc == 0) {
- /* Disallow "\u0000". */
- goto failed;
- } else {
- unicode = uc;
- }
-
- b += utf8_write_char(unicode, b);
- break;
- }
- default:
- /* Invalid escape */
- goto failed;
- }
- } else if (c <= 0x1F) {
- /* Control characters are not allowed in string literals. */
- goto failed;
- } else {
- /* Validate and echo a UTF-8 character. */
- int len;
-
- s--;
- len = utf8_validate_cz(s);
- if (len == 0)
- goto failed; /* Invalid UTF-8 character. */
-
- while (len--)
- *b++ = *s++;
- }
-
- /*
- * Update sb to know about the new bytes,
- * and set up b to write another character.
- */
- if (out) {
- sb.cur = b;
- sb_need(&sb, 4);
- b = sb.cur;
- } else {
- b = throwaway_buffer;
- }
- }
- s++;
-
- if (out)
- *out = sb_finish(&sb);
- *sp = s;
- return true;
- failed:
- if (out)
- sb_free(&sb);
- return false;
- }
- /*
- * The JSON spec says that a number shall follow this precise pattern
- * (spaces and quotes added for readability):
- * '-'? (0 | [1-9][0-9]*) ('.' [0-9]+)? ([Ee] [+-]? [0-9]+)?
- *
- * However, some JSON parsers are more liberal. For instance, PHP accepts
- * '.5' and '1.'. JSON.parse accepts '+3'.
- *
- * This function takes the strict approach.
- */
- bool parse_number(const char **sp, double *out)
- {
- const char *s = *sp;
- /* '-'? */
- if (*s == '-')
- s++;
- /* (0 | [1-9][0-9]*) */
- if (*s == '0') {
- s++;
- } else {
- if (!is_digit(*s))
- return false;
- do {
- s++;
- } while (is_digit(*s));
- }
- /* ('.' [0-9]+)? */
- if (*s == '.') {
- s++;
- if (!is_digit(*s))
- return false;
- do {
- s++;
- } while (is_digit(*s));
- }
- /* ([Ee] [+-]? [0-9]+)? */
- if (*s == 'E' || *s == 'e') {
- s++;
- if (*s == '+' || *s == '-')
- s++;
- if (!is_digit(*s))
- return false;
- do {
- s++;
- } while (is_digit(*s));
- }
- if (out)
- *out = strtod(*sp, NULL);
- *sp = s;
- return true;
- }
- static void skip_space(const char **sp)
- {
- const char *s = *sp;
- while (is_space(*s))
- s++;
- *sp = s;
- }
- static void emit_value(SB *out, const JsonNode *node)
- {
- assert(tag_is_valid(node->tag));
- switch (node->tag) {
- case JSON_NULL:
- sb_puts(out, "null");
- break;
- case JSON_BOOL:
- sb_puts(out, node->bool_ ? "true" : "false");
- break;
- case JSON_STRING:
- emit_string(out, node->string_);
- break;
- case JSON_NUMBER:
- emit_number(out, node->number_);
- break;
- case JSON_ARRAY:
- emit_array(out, node);
- break;
- case JSON_OBJECT:
- emit_object(out, node);
- break;
- default:
- assert(false);
- }
- }
- void emit_value_indented(SB *out, const JsonNode *node, const char *space, int indent_level)
- {
- assert(tag_is_valid(node->tag));
- switch (node->tag) {
- case JSON_NULL:
- sb_puts(out, "null");
- break;
- case JSON_BOOL:
- sb_puts(out, node->bool_ ? "true" : "false");
- break;
- case JSON_STRING:
- emit_string(out, node->string_);
- break;
- case JSON_NUMBER:
- emit_number(out, node->number_);
- break;
- case JSON_ARRAY:
- emit_array_indented(out, node, space, indent_level);
- break;
- case JSON_OBJECT:
- emit_object_indented(out, node, space, indent_level);
- break;
- default:
- assert(false);
- }
- }
- static void emit_array(SB *out, const JsonNode *array)
- {
- const JsonNode *element;
-
- sb_putc(out, '[');
- json_foreach(element, array) {
- emit_value(out, element);
- if (element->next != NULL)
- sb_putc(out, ',');
- }
- sb_putc(out, ']');
- }
- static void emit_array_indented(SB *out, const JsonNode *array, const char *space, int indent_level)
- {
- const JsonNode *element = array->children.head;
- int i;
-
- if (element == NULL) {
- sb_puts(out, "[]");
- return;
- }
-
- sb_puts(out, "[\n");
- while (element != NULL) {
- for (i = 0; i < indent_level + 1; i++)
- sb_puts(out, space);
- emit_value_indented(out, element, space, indent_level + 1);
-
- element = element->next;
- sb_puts(out, element != NULL ? ",\n" : "\n");
- }
- for (i = 0; i < indent_level; i++)
- sb_puts(out, space);
- sb_putc(out, ']');
- }
- static void emit_object(SB *out, const JsonNode *object)
- {
- const JsonNode *member;
-
- sb_putc(out, '{');
- json_foreach(member, object) {
- emit_string(out, member->key);
- sb_putc(out, ':');
- emit_value(out, member);
- if (member->next != NULL)
- sb_putc(out, ',');
- }
- sb_putc(out, '}');
- }
- static void emit_object_indented(SB *out, const JsonNode *object, const char *space, int indent_level)
- {
- const JsonNode *member = object->children.head;
- int i;
-
- if (member == NULL) {
- sb_puts(out, "{}");
- return;
- }
-
- sb_puts(out, "{\n");
- while (member != NULL) {
- for (i = 0; i < indent_level + 1; i++)
- sb_puts(out, space);
- emit_string(out, member->key);
- sb_puts(out, ": ");
- emit_value_indented(out, member, space, indent_level + 1);
-
- member = member->next;
- sb_puts(out, member != NULL ? ",\n" : "\n");
- }
- for (i = 0; i < indent_level; i++)
- sb_puts(out, space);
- sb_putc(out, '}');
- }
- void emit_string(SB *out, const char *str)
- {
- bool escape_unicode = false;
- const char *s = str;
- char *b;
-
- assert(utf8_validate(str));
-
- /*
- * 14 bytes is enough space to write up to two
- * \uXXXX escapes and two quotation marks.
- */
- sb_need(out, 14);
- b = out->cur;
-
- *b++ = '"';
- while (*s != 0) {
- unsigned char c = *s++;
-
- /* Encode the next character, and write it to b. */
- switch (c) {
- case '"':
- *b++ = '\\';
- *b++ = '"';
- break;
- case '\\':
- *b++ = '\\';
- *b++ = '\\';
- break;
- case '\b':
- *b++ = '\\';
- *b++ = 'b';
- break;
- case '\f':
- *b++ = '\\';
- *b++ = 'f';
- break;
- case '\n':
- *b++ = '\\';
- *b++ = 'n';
- break;
- case '\r':
- *b++ = '\\';
- *b++ = 'r';
- break;
- case '\t':
- *b++ = '\\';
- *b++ = 't';
- break;
- default: {
- int len;
-
- s--;
- len = utf8_validate_cz(s);
-
- if (len == 0) {
- /*
- * Handle invalid UTF-8 character gracefully in production
- * by writing a replacement character (U+FFFD)
- * and skipping a single byte.
- *
- * This should never happen when assertions are enabled
- * due to the assertion at the beginning of this function.
- */
- assert(false);
- if (escape_unicode) {
- strcpy(b, "\\uFFFD");
- b += 6;
- } else {
- *b++ = 0xEF;
- *b++ = 0xBF;
- *b++ = 0xBD;
- }
- s++;
- } else if (c < 0x1F || (c >= 0x80 && escape_unicode)) {
- /* Encode using \u.... */
- uint32_t unicode;
-
- s += utf8_read_char(s, &unicode);
-
- if (unicode <= 0xFFFF) {
- *b++ = '\\';
- *b++ = 'u';
- b += write_hex16(b, unicode);
- } else {
- /* Produce a surrogate pair. */
- uint16_t uc, lc;
- assert(unicode <= 0x10FFFF);
- to_surrogate_pair(unicode, &uc, &lc);
- *b++ = '\\';
- *b++ = 'u';
- b += write_hex16(b, uc);
- *b++ = '\\';
- *b++ = 'u';
- b += write_hex16(b, lc);
- }
- } else {
- /* Write the character directly. */
- while (len--)
- *b++ = *s++;
- }
-
- break;
- }
- }
-
- /*
- * Update *out to know about the new bytes,
- * and set up b to write another encoded character.
- */
- out->cur = b;
- sb_need(out, 14);
- b = out->cur;
- }
- *b++ = '"';
-
- out->cur = b;
- }
- static void emit_number(SB *out, double num)
- {
- /*
- * This isn't exactly how JavaScript renders numbers,
- * but it should produce valid JSON for reasonable numbers
- * preserve precision well enough, and avoid some oddities
- * like 0.3 -> 0.299999999999999988898 .
- */
- char buf[64];
- sprintf(buf, "%.16g", num);
-
- if (number_is_valid(buf))
- sb_puts(out, buf);
- else
- sb_puts(out, "null");
- }
- static bool tag_is_valid(unsigned int tag)
- {
- return (/* tag >= JSON_NULL && */ tag <= JSON_OBJECT);
- }
- static bool number_is_valid(const char *num)
- {
- return (parse_number(&num, NULL) && *num == '\0');
- }
- static bool expect_literal(const char **sp, const char *str)
- {
- const char *s = *sp;
-
- while (*str != '\0')
- if (*s++ != *str++)
- return false;
-
- *sp = s;
- return true;
- }
- /*
- * Parses exactly 4 hex characters (capital or lowercase).
- * Fails if any input chars are not [0-9A-Fa-f].
- */
- static bool parse_hex16(const char **sp, uint16_t *out)
- {
- const char *s = *sp;
- uint16_t ret = 0;
- uint16_t i;
- uint16_t tmp;
- char c;
- for (i = 0; i < 4; i++) {
- c = *s++;
- if (c >= '0' && c <= '9')
- tmp = c - '0';
- else if (c >= 'A' && c <= 'F')
- tmp = c - 'A' + 10;
- else if (c >= 'a' && c <= 'f')
- tmp = c - 'a' + 10;
- else
- return false;
- ret <<= 4;
- ret += tmp;
- }
-
- if (out)
- *out = ret;
- *sp = s;
- return true;
- }
- /*
- * Encodes a 16-bit number into hexadecimal,
- * writing exactly 4 hex chars.
- */
- static int write_hex16(char *out, uint16_t val)
- {
- const char *hex = "0123456789ABCDEF";
-
- *out++ = hex[(val >> 12) & 0xF];
- *out++ = hex[(val >> 8) & 0xF];
- *out++ = hex[(val >> 4) & 0xF];
- *out++ = hex[ val & 0xF];
-
- return 4;
- }
- bool json_check(const JsonNode *node, char errmsg[256])
- {
- #define problem(...) do { \
- if (errmsg != NULL) \
- snprintf(errmsg, 256, __VA_ARGS__); \
- return false; \
- } while (0)
-
- if (node->key != NULL && !utf8_validate(node->key))
- problem("key contains invalid UTF-8");
-
- if (!tag_is_valid(node->tag))
- problem("tag is invalid (%u)", node->tag);
-
- if (node->tag == JSON_BOOL) {
- if (node->bool_ != false && node->bool_ != true)
- problem("bool_ is neither false (%d) nor true (%d)", (int)false, (int)true);
- } else if (node->tag == JSON_STRING) {
- if (node->string_ == NULL)
- problem("string_ is NULL");
- if (!utf8_validate(node->string_))
- problem("string_ contains invalid UTF-8");
- } else if (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT) {
- JsonNode *head = node->children.head;
- JsonNode *tail = node->children.tail;
-
- if (head == NULL || tail == NULL) {
- if (head != NULL)
- problem("tail is NULL, but head is not");
- if (tail != NULL)
- problem("head is NULL, but tail is not");
- } else {
- JsonNode *child;
- JsonNode *last = NULL;
-
- if (head->prev != NULL)
- problem("First child's prev pointer is not NULL");
-
- for (child = head; child != NULL; last = child, child = child->next) {
- if (child == node)
- problem("node is its own child");
- if (child->next == child)
- problem("child->next == child (cycle)");
- if (child->next == head)
- problem("child->next == head (cycle)");
-
- if (child->parent != node)
- problem("child does not point back to parent");
- if (child->next != NULL && child->next->prev != child)
- problem("child->next does not point back to child");
-
- if (node->tag == JSON_ARRAY && child->key != NULL)
- problem("Array element's key is not NULL");
- if (node->tag == JSON_OBJECT && child->key == NULL)
- problem("Object member's key is NULL");
-
- if (!json_check(child, errmsg))
- return false;
- }
-
- if (last != tail)
- problem("tail does not match pointer found by starting at head and following next links");
- }
- }
-
- return true;
-
- #undef problem
- }
|