// This file is in the public domain. #include #include #include #include #include #include typedef struct parser PARSER; typedef struct eub EUB; typedef struct dec_ucp_len_priv DEC_UCP_LEN_PRIV; typedef struct dec_ascii_cb_priv DEC_ASCII_CB_PRIV; typedef struct dec_ascii_len_priv DEC_ASCII_LEN_PRIV; typedef struct dec_utf8_common_priv DEC_UTF8_COMMON_PRIV; typedef struct dec_utf8_cb_priv DEC_UTF8_CB_PRIV; typedef struct dec_utf8_len_priv DEC_UTF8_LEN_PRIV; typedef struct dec_utf8_nul_priv DEC_UTF8_NUL_PRIV; typedef struct encoder ENCODER; typedef struct enc_ascii_priv ENC_ASCII_PRIV; typedef struct enc_utf8_priv ENC_UTF8_PRIV; struct enc_utf8_priv { void (*cb)(unsigned char, void *); void *cbarg; } ; struct enc_ascii_priv { void (*cb)(char, void *); void *cbarg; } ; struct encoder { void (*cb)(JSON_UCP, void *); void *cbarg; int flags; } ; struct dec_utf8_common_priv { unsigned char nb; unsigned char b[4]; unsigned char x; } ; struct dec_utf8_nul_priv { DEC_UTF8_COMMON_PRIV c; const unsigned char *txt; int x; } ; struct dec_utf8_len_priv { DEC_UTF8_COMMON_PRIV c; const unsigned char *txt; int len; int x; } ; struct dec_utf8_cb_priv { DEC_UTF8_COMMON_PRIV c; int (*cb)(void *); void *cbarg; } ; struct dec_ascii_len_priv { const char *txt; int len; int x; } ; struct dec_ascii_cb_priv { int (*cb)(void *); void *cbarg; } ; struct dec_ucp_len_priv { const JSON_UCP *txt; int len; int x; } ; struct eub { JSON_UCP *b; int a; int l; } ; struct parser { JSON_UCP (*ch)(void *); void *arg; JSON_UCP c; unsigned int flags; } ; static JSON_VAL parse(PARSER *); // forward static JSON_ENC_RV encode(JSON_VAL, ENCODER *); // forward static void pch(PARSER *p) { p->c = (*p->ch)(p->arg); } static void skipws(PARSER *p) { while (1) { switch (p->c) { case 0x20: case 0x09: case 0x0a: case 0x0d: pch(p); break; default: return; break; } } } static int parse_keyword(PARSER *p, const char *key) { while (*key) { if (p->c != *key) return(0); pch(p); key ++; } return(1); } static void eub_init(EUB *e) { e->b = 0; e->a = 0; e->l = 0; } static void eub_done(EUB *e) { free(e->b); e->b = 0; e->a = 0; e->l = 0; } static void eub_append_1(EUB *e, JSON_UCP c) { if (e->l >= e->a) e->b = realloc(e->b,(e->a=e->l+16)*sizeof(*e->b)); e->b[e->l++] = c; } static int eub_len(EUB *e) { return(e->l); } static JSON_UCP *eub_ptr(EUB *e) { return(e->b); } static void eub_drop_last_1(EUB *e) { if (e->l < 1) abort(); e->l --; } static void utf8_init(DEC_UTF8_COMMON_PRIV *p) { p->nb = 0; p->x = 0; } static int utf8_midseq(DEC_UTF8_COMMON_PRIV *p) { return(p->nb>0); } #define UTF8_NOTHING 0xf0000000 #define UTF8_ERROR 0xf0000001 static JSON_UCP utf8_input(DEC_UTF8_COMMON_PRIV *p, unsigned char b) { JSON_UCP c; JSON_UCP min; JSON_UCP max; if (p->nb == 0) { if ((b & 0x80) == 0) { return(b); } else if ((b & 0xe0) == 0xc0) { p->nb = 2; } else if ((b & 0xf0) == 0xe0) { p->nb = 3; } else if ((b & 0xf8) == 0xf0) { p->nb = 4; } else { return(UTF8_ERROR); } p->x = 0; } if (p->x > 3) abort(); if ((p->x > 0) && ((b & 0xc0) != 0x80)) return(UTF8_ERROR); p->b[p->x++] = b; if (p->x < p->nb) return(UTF8_NOTHING); switch (p->nb) { case 2: min = 0x000080; max = 0x0007ff; c = ((p->b[0] & 0x1f) << 6) | (p->b[1] & 0x3f); break; case 3: min = 0x000800; max = 0x00ffff; c = ((p->b[0] & 0x1f) << 12) | ((p->b[2] & 0x3f) << 6) | (p->b[2] & 0x3f); break; case 4: min = 0x010000; max = 0x10ffff; c = ((p->b[0] & 0x1f) << 18) | ((p->b[2] & 0x3f) << 12) | ((p->b[3] & 0x3f) << 6) | (p->b[4] & 0x3f); break; default: abort(); break; } if ((c < min) || (c > max)) return(UTF8_ERROR); p->nb = 0; return(c); } static JSON_VAL jval_err(const char *, ...) __attribute__((__format__(__printf__,1,2))); static JSON_VAL jval_err(const char *fmt, ...) { char *s; va_list ap; va_start(ap,fmt); vasprintf(&s,fmt,ap); va_end(ap); return((JSON_VAL){.type=JVT_ERR,.u={.err=s}}); } static JSON_VAL jval_err_v(const char *, va_list) __attribute__((__format__(__printf__,1,0))); static JSON_VAL jval_err_v(const char *fmt, va_list ap) { char *s; vasprintf(&s,fmt,ap); return((JSON_VAL){.type=JVT_ERR,.u={.err=s}}); } static JSON_VAL jval_eof(void) { return((JSON_VAL){.type=JVT_EOF}); } static JSON_VAL jval_null(void) { return((JSON_VAL){.type=JVT_NULL}); } static JSON_VAL jval_bool(int tv) { return((JSON_VAL){.type=JVT_BOOL,.u={.b=tv?1:0}}); } static JSON_VAL jval_num(double v) { return((JSON_VAL){.type=JVT_NUM,.u={.n=v}}); } // jval_str() needs to have strings and flags set static JSON_VAL jval_str(void) { return((JSON_VAL){.type=JVT_STR,.u={.s={.flags=0}}}); } static JSON_VAL jval_obj(int num, JSON_OBJENT *vec) { return((JSON_VAL){.type=JVT_OBJ,.u={.o={.n=num,.v=vec}}}); } static JSON_VAL jval_arr(int num, JSON_VAL *vec) { return((JSON_VAL){.type=JVT_ARR,.u={.a={.n=num,.v=vec}}}); } /* * array [ (val (, val)*)? ] */ static JSON_VAL parse_array(PARSER *p) { JSON_VAL *v; int a; int n; JSON_VAL val; pch(p); skipws(p); if (p->c == 0x5d) { pch(p); return(jval_arr(0,0)); } v = 0; a = 0; n = 0; do <"done"> { while <"fail"> (1) { val = parse(p); switch (val.type) { case JVT_ERR: break <"fail">; case JVT_EOF: json_val_drop(val); val = jval_err("EOF when expecting value in object"); break <"fail">; default: break; } if (n >= a) v = realloc(v,(a=n+8)*sizeof(*v)); v[n++] = val; skipws(p); switch (p->c) { case 0x2c: pch(p); break; case 0x5d: pch(p); break <"done">; case JSON_UCP_EOF: val = jval_err("EOF after value in array"); break <"fail">; case JSON_UCP_ERR: val = jval_err("error codepoint after value in array"); break <"fail">; default: val = jval_err("invalid character 0x%x after value in array",p->c); break <"fail">; } } while (n > 0) { n --; json_val_drop(v[n]); } return(val); } while (0); return(jval_arr(n,v)); } /* * str " ch* " * ch unesc | \ esc * unesc 0x20-0x21 0x23-0x5b 0x5d-0x10ffff * esc ["\/bfnrt] | [u] xdig*4 * xdig [0-9a-fA-F] * Unicode codepoints outside BMP are encoded as a surrogate pair: * cp=0x10000-0x10ffff encoded as: * (1) Subtract 0x10000, leaving a number in 0x00000-0xfffff * (2) High ten bits are added to 0xd800, giving high surrogate (first) * (3) Low ten bits are added to 0xdc00, giving low surrogate (second) */ static JSON_VAL parse_string(PARSER *p) { int esc; EUB str; JSON_UCP c; unsigned int dv; JSON_VAL rv; int i; JSON_UCP *up; int l; pch(p); esc = 0; eub_init(&str); while <"str"> (1) { switch (esc) { case 0: switch (p->c) { case 0x22: pch(p); break <"str">; case 0x5c: esc = 1; break; case JSON_UCP_EOF: eub_done(&str); return(jval_err("JSON ends within a string")); break; case JSON_UCP_ERR: eub_done(&str); return(jval_err("error codepoint in string")); break; default: if (p->c > 0x10ffff) { eub_done(&str); return(jval_err("invalid codepoint %x in string",p->c)); } eub_append_1(&str,p->c); break; } break; case 1: switch (p->c) { case 0x22: case 0x5c: case 0x2f: c = p->c; if (0) { case 0x62: c = 0x08; } if (0) { case 0x66: c = 0x0c; } if (0) { case 0x6e: c = 0x0a; } if (0) { case 0x72: c = 0x0d; } if (0) { case 0x74: c = 0x09; } esc = 0; eub_append_1(&str,c); break; case 0x75: esc = 2; c = 0; break; default: eub_done(&str); return(jval_err("invalid escape %x in string",p->c)); break; } break; case 2: case 3: case 4: case 5: switch (p->c) { case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: dv = p->c - 0x30; break; case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: dv = p->c - 0x61 + 10; break; case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: dv = p->c - 0x41 + 10; break; default: eub_done(&str); return(jval_err("invalid hex digit %x after \\u in string",p->c)); break; } c = (c << 4) | dv; esc ++; if (esc > 5) { if ((c >= 0xdc00) && (c <= 0xdfff)) { JSON_UCP pc; l = eub_len(&str); if (l > 0) { pc = eub_ptr(&str)[l-1]; if ((pc >= 0xd800) && (pc <= 0xdbff)) { c = (((pc & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; eub_drop_last_1(&str); } } } eub_append_1(&str,c); esc = 0; } break; default: abort(); break; } pch(p); } rv = jval_str(); rv.u.s.flags |= JSON_S_F_UNICODE; rv.u.s.len = eub_len(&str); rv.u.s.ucp = malloc(rv.u.s.len*sizeof(JSON_UCP)); up = rv.u.s.ucp; bcopy(eub_ptr(&str),up,rv.u.s.len*sizeof(JSON_UCP)); do <"ascii"> { for (i=rv.u.s.len-1;i>=0;i--) if (up[i] >= 128) break <"ascii">; rv.u.s.flags |= JSON_S_F_ASCII; rv.u.s.ascii = malloc(rv.u.s.len); for (i=rv.u.s.len-1;i>=0;i--) rv.u.s.ascii[i] = up[i]; } while (0); eub_done(&str); #if 0 if (p->flags & JSON_API_UTF8) { l = 0; for (i=rv.u.s.len-1;i>=0;i--) { if (up[i] < 128) l ++; else if (up[i] < 0x800) l += 2; else if (up[i] < 0x10000) l += 3; else if (up[i] < 0x110000) l += 4; else abort(); } rv.u.s.flags |= JSON_S_F_UTF8; rv.u.s.utf8len = l; rv.u.s.utf8 = malloc(l); x = 0; for (i=0;i l) abort(); rv.u.s.utf8[x++] = up[i]; } else if (up[i] < 0x800) { if (x+2 > l) abort(); rv.u.s.utf8[x++] = 0xc0 | (up[i] >> 6); rv.u.s.utf8[x++] = 0x80 | (up[i] & 0x3f); } else if (up[i] < 0x10000) { if (x+3 > l) abort(); rv.u.s.utf8[x++] = 0xc0 | (up[i] >> 12); rv.u.s.utf8[x++] = 0x80 | ((up[i] >> 6) & 0x3f); rv.u.s.utf8[x++] = 0x80 | (up[i] & 0x3f); } else if (up[i] < 0x110000) { if (x+4 > l) abort(); rv.u.s.utf8[x++] = 0xc0 | (up[i] >> 18); rv.u.s.utf8[x++] = 0x80 | ((up[i] >> 12) & 0x3f); rv.u.s.utf8[x++] = 0x80 | ((up[i] >> 6) & 0x3f); rv.u.s.utf8[x++] = 0x80 | (up[i] & 0x3f); } else { abort(); } } if (x != l) abort(); } #endif return(rv); } /* * object { (string : val (, string : val)*)? } */ static JSON_VAL parse_object(PARSER *p) { JSON_OBJENT *v; int a; int n; JSON_VAL label; JSON_VAL value; pch(p); skipws(p); if (p->c == 0x7d) { pch(p); return(jval_obj(0,0)); } v = 0; a = 0; n = 0; do <"done"> { while <"fail"> (1) { skipws(p); if (p->c != 0x22) { value = jval_err("object member name isn't a string"); break <"fail">; } label = parse_string(p); switch (label.type) { case JVT_STR: break; case JVT_ERR: value = label; break <"fail">; break; default: abort(); // parse_string can't return any other types break; } skipws(p); if (p->c != 0x3a) { json_val_drop(label); value = jval_err("invalid separator after object label"); break <"fail">; } pch(p); value = parse(p); switch (value.type) { case JVT_ERR: json_val_drop(label); break <"fail">; case JVT_EOF: json_val_drop(label); value = jval_err("EOF when expecting value in object"); break <"fail">; default: break; } if (n >= a) v = realloc(v,(a=n+8)*sizeof(*v)); v[n++] = (JSON_OBJENT){.key=label,.val=value}; skipws(p); switch (p->c) { case 0x2c: pch(p); break; case 0x7d: pch(p); break <"done">; case JSON_UCP_EOF: value = jval_err("EOF after value in object"); break <"fail">; case JSON_UCP_ERR: value = jval_err("error codepoint after value in object"); break <"fail">; default: value = jval_err("invalid character %x after value in object",p->c); break <"fail">; } } while (n > 0) { n --; json_val_drop(v[n].key); json_val_drop(v[n].val); } return(value); } while (0); return(jval_obj(n,v)); } /* * num -? int frac? exp? * int 0 | [1-9] [0-9]* * frac . [0-9]+ * exp [eE] [-+]? [0-9]* */ static JSON_VAL parse_number(PARSER *p) { int neg; int ndig; int dot; int negexp; int exp; int edig; double mval; neg = 0; ndig = 0; dot = -1; negexp = 0; exp = -1; edig = -1; mval = 0; if (p->c == 0x2d) { neg = 1; pch(p); } switch (p->c) { case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: mval = p->c - 0x30; ndig = 1; pch(p); break; default: return(jval_err("number begins with invalid digit 0x%x",p->c)); break; } while (1) { switch (p->c) { case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: if (exp < 0) { mval = (mval * 10) + (p->c - 0x30); ndig ++; } else { exp = (exp * 10) + (p->c - 0x30); if (edig < 0) edig = 0; edig ++; } pch(p); break; case 0x2e: if (dot >= 0) return(jval_err("number contains multiple dots")); dot = ndig; pch(p); break; case 0x65: case 0x45: exp = 0; pch(p); break; case 0x2d: if ((exp == 0) && (edig < 0)) { negexp = 1; edig = 0; break; } if (0) { case 0x2b: if ((exp == 0) && (edig < 0)) { edig = 0; break; } } /* fall through */ default: if (dot == ndig) return(jval_err("number has no digits after dot")); if ((exp >= 0) && (edig == 0)) return(jval_err("number has exponent marker but no exponent")); return(jval_num(mval*pow(10,(((dot<0)?0:dot-ndig)+((exp<0)?0:negexp?-exp:exp)))*(neg?-1:1))); break; } } } static JSON_VAL parse(PARSER *p) { skipws(p); switch (p->c) { case JSON_UCP_EOF: return(jval_eof()); break; case JSON_UCP_ERR: return(jval_err("error codepoint seen")); break; case 0x6e: // null if (parse_keyword(p,"\x6e\x75\x6c\x6c")) return(jval_null()); return(jval_err("invalid keyword")); break; case 0x66: // false if (parse_keyword(p,"\x66\x61\x6c\x73\x65")) return(jval_bool(0)); return(jval_err("invalid keyword")); break; case 0x74: // true if (parse_keyword(p,"\x74\x72\x75\x65")) return(jval_bool(1)); return(jval_err("invalid keyword")); break; case 0x5b: // array return(parse_array(p)); break; case 0x7b: // object return(parse_object(p)); break; case 0x22: // string return(parse_string(p)); break; case 0x2d: case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: return(parse_number(p)); break; } return(jval_err("value begins with invalid codepoint %x",p->c)); } static JSON_UCP json_decode__ucp_len_cb(void *pv) { DEC_UCP_LEN_PRIV *p; p = pv; if (p->x >= p->len) return(JSON_UCP_EOF); return(p->txt[p->x++]); } static JSON_UCP json_decode__ascii_cb(void *pv) { DEC_ASCII_CB_PRIV *p; int ch; p = pv; ch = (*p->cb)(p->cbarg); if (ch == -1) return(JSON_UCP_EOF); if ((ch < 0) || (ch > 127)) return(JSON_UCP_ERR); return(ch); } static JSON_UCP json_decode__ascii_len(void *pv) { DEC_ASCII_LEN_PRIV *p; int ch; p = pv; if (p->x >= p->len) return(JSON_UCP_EOF); ch = p->txt[p->x++]; if ((ch < 0) || (ch > 127)) return(JSON_UCP_ERR); return(ch); } static JSON_UCP json_decode__ascii_nul(void *pv) { const char **txtp; int ch; txtp = pv; ch = **txtp; if (ch) ++*txtp; if (ch == 0) return(JSON_UCP_EOF); if ((ch < 0) || (ch > 127)) return(JSON_UCP_ERR); return(ch); } static JSON_UCP json_decode__utf8_cb(void *pv) { DEC_UTF8_CB_PRIV *p; unsigned int c; p = pv; while (1) { c = (*p->cb)(p->cbarg); if (c == -1) { if (utf8_midseq(&p->c)) return(JSON_UCP_ERR); return(JSON_UCP_EOF); } if ((c < -1) || (c > 255)) return(JSON_UCP_ERR); c = utf8_input(&p->c,c); if (c == UTF8_NOTHING) continue; if (c == UTF8_ERROR) return(JSON_UCP_ERR); return(c); } } static JSON_UCP json_decode__utf8_len(void *pv) { DEC_UTF8_LEN_PRIV *p; unsigned int c; p = pv; while (1) { if (p->x >= p->len) { if (utf8_midseq(&p->c)) return(JSON_UCP_ERR); return(JSON_UCP_EOF); } c = utf8_input(&p->c,p->txt[p->x++]); if (c == UTF8_NOTHING) continue; if (c == UTF8_ERROR) return(JSON_UCP_ERR); return(c); } } static JSON_UCP json_decode__utf8_nul(void *pv) { DEC_UTF8_NUL_PRIV *p; unsigned int c; p = pv; while (1) { c = p->txt[p->x]; if (! c) { if (utf8_midseq(&p->c)) return(JSON_UCP_ERR); return(JSON_UCP_EOF); } c = utf8_input(&p->c,c); if (c == UTF8_NOTHING) continue; if (c == UTF8_ERROR) return(JSON_UCP_ERR); return(c); } } static JSON_ENC_RV encode_keyword(ENCODER *e, const void *key) { const unsigned char *k; for (k=key;*k;k++) { (*e->cb)(*k,e->cbarg); } return(JES_OK); } /* * On systems that have infinities and/or NaN, we just count on * snprintf to generate a string that trips the JES_ERR return. */ static JSON_ENC_RV encode_number(ENCODER *e, double v) { char b[64]; int l; int i; unsigned int c; l = snprintf(&b[0],sizeof(b),"%g",v); for (i=0;icb)(c,e->cbarg); } return(JES_OK); } static void enc_u4hex(ENCODER *e, unsigned int v) { int s; (*e->cb)(0x5c,e->cbarg); (*e->cb)(0x75,e->cbarg); for (s=12;s>=0;s-=4) (*e->cb)("0123456789abcdef"[(v>>s)&15],e->cbarg); } static int encode_string_contents(ENCODER *e, const JSON_STR *s, JSON_UCP (*cb)(const JSON_STR *, void *), void *cbarg) { JSON_UCP cp; char c2; while (1) { cp = (*cb)(s,cbarg); switch (cp) { case JSON_UCP_EOF: return(0); case JSON_UCP_ERR: return(1); break; case 0x22: case 0x5c: (*e->cb)(0x5c,e->cbarg); (*e->cb)(cp,e->cbarg); break; } if (cp > 0x10ffff) return(1); if ((cp >= 128) && (e->flags & JSON_API_ASCII)) { if (cp > 0xffff) { enc_u4hex(e,0xd800+((cp-0x10000)>>10)); enc_u4hex(e,0xdc00+((cp-0x10000)&0x3ff)); } else { enc_u4hex(e,cp); } } else if (cp < 32) { switch (cp) { case 0x08: c2 = 0x62; if (0) { case 0x0c: c2 = 0x66; } if (0) { case 0x0a: c2 = 0x6e; } if (0) { case 0x0d: c2 = 0x72; } if (0) { case 0x09: c2 = 0x74; } (*e->cb)(0x5c,e->cbarg); (*e->cb)(c2,e->cbarg); break; default: enc_u4hex(e,cp); break; } } else { (*e->cb)(cp,e->cbarg); } } } static JSON_UCP string_ascii(const JSON_STR *s, void *pv) { int x; int c; x = *(int *)pv; if (x >= s->len) return(JSON_UCP_EOF); c = s->ascii[x++]; if ((c < 0) || (c > 127)) return(JSON_UCP_ERR); *(int *)pv = x; return(c); } static JSON_UCP string_unicode(const JSON_STR *s, void *pv) { int x; JSON_UCP c; x = *(int *)pv; if (x >= s->len) return(JSON_UCP_EOF); c = s->ucp[x++]; if (c > 0x10ffff) return(JSON_UCP_ERR); *(int *)pv = x; return(c); } #if 0 static JSON_UCP string_utf8(const JSON_STR *s, void *pv) { int x; JSON_UCP c; JSON_UCP min; unsigned char o; int shift; x = *(int *)pv; shift = -1; while (1) { if (x >= s->utf8len) return((shift<0)?JSON_UCP_EOF:JSON_UCP_ERR); o = s->utf8[x++]; if (shift < 0) { if ((o & 0x80) == 0) { min = 0; c = o; break; } else if ((o & 0xe0) == 0xc0) { min = 0x80; shift = 0; c = (o & 0x1f) << 6; } else if ((o & 0xf0) == 0xe0) { min = 0x800; shift = 6; c = (o & 0x0f) << 12; } else if ((o & 0xf8) == 0xf0) { min = 0x10000; shift = 12; c = (o & 0x07) << 18; } else { return(JSON_UCP_ERR); } } else { if ((o & 0xc0) != 0x80) return(JSON_UCP_ERR); c |= (o & 0x3f) << shift; shift -= 6; if (shift < 0) break; } } if ((c < min) || (c > 0x10ffff)) return(JSON_UCP_ERR); *(int *)pv = x; return(c); } #endif static JSON_ENC_RV encode_string(ENCODER *e, JSON_STR *s) { int x; (*e->cb)(0x22,e->cbarg); if (s->flags & JSON_S_F_ASCII) { x = 0; if (encode_string_contents(e,s,&string_ascii,&x)) return(JES_ERR); } else if (s->flags & JSON_S_F_UNICODE) { x = 0; if (encode_string_contents(e,s,&string_unicode,&x)) return(JES_ERR); } #if 0 else if (s->flags & JSON_S_F_UTF8) { x = 0; if (encode_string_contents(e,s,&string_utf8,&x)) return(JES_ERR); } #endif else { return(JES_ERR); } (*e->cb)(0x22,e->cbarg); return(JES_OK); } static JSON_ENC_RV encode_object(ENCODER *e, JSON_VAL v) { int i; JSON_ENC_RV r; if (v.type != JVT_OBJ) abort(); (*e->cb)(0x7b,e->cbarg); for (i=0;icb)(0x2c,e->cbarg); if (v.u.o.v[i].key.type != JVT_STR) return(JES_ERR); r = encode_string(e,&v.u.o.v[i].key.u.s); if (r != JES_OK) return(r); (*e->cb)(0x3a,e->cbarg); r = encode(v.u.o.v[i].val,e); } (*e->cb)(0x7d,e->cbarg); return(JES_OK); } static JSON_ENC_RV encode_array(ENCODER *e, JSON_VAL v) { int i; JSON_ENC_RV r; if (v.type != JVT_ARR) abort(); (*e->cb)(0x5b,e->cbarg); for (i=0;icb)(0x2c,e->cbarg); r = encode(v.u.a.v[i],e); if (r != JES_OK) return(r); } (*e->cb)(0x5d,e->cbarg); return(JES_OK); } static JSON_ENC_RV encode(JSON_VAL v, ENCODER *e) { switch (v.type) { default: return(JES_ERR); break; case JVT_NULL: return(encode_keyword(e,"\x6e\x75\x6c\x6c")); break; case JVT_BOOL: return(encode_keyword(e,v.u.b?"\x74\x72\x75\x65":"\x66\x61\x6c\x73\x65")); break; case JVT_NUM: return(encode_number(e,v.u.n)); break; case JVT_STR: return(encode_string(e,&v.u.s)); break; case JVT_OBJ: return(encode_object(e,v)); break; case JVT_ARR: return(encode_array(e,v)); break; } } static void enc_ascii_cb(JSON_UCP c, void *pv) { ENC_ASCII_PRIV *p; p = pv; (*p->cb)(c,p->cbarg); } static void enc_utf8_cb(JSON_UCP c, void *pv) { ENC_UTF8_PRIV *p; p = pv; if (c < 0x80) { (*p->cb)(c,p->cbarg); } else if (c < 0x800) { (*p->cb)(((c>>6)&0x1f)|0xc0,p->cbarg); (*p->cb)((c&0x3f)|0x80,p->cbarg); } else if (c < 0x10000) { (*p->cb)(((c>>12)&0x0f)|0xe0,p->cbarg); (*p->cb)(((c>>6)&0x3f)|0x80,p->cbarg); (*p->cb)((c&0x3f)|0x80,p->cbarg); } else if (c < 0x110000) { (*p->cb)(((c>>18)&0x07)|0xf0,p->cbarg); (*p->cb)(((c>>12)&0x3f)|0x80,p->cbarg); (*p->cb)(((c>>6)&0x3f)|0x80,p->cbarg); (*p->cb)((c&0x3f)|0x80,p->cbarg); } else { abort(); } } static int find_cb_common(JSON_VAL obj, int (*cb)(JSON_VAL, void *), void *cbarg, int (*match)(const JSON_STR *)) { int i; JSON_VAL k; int rv; int subrv; if (obj.type != JVT_OBJ) return(-1); rv = 0; for (i=obj.u.o.n-1;i>=0;i--) { k = obj.u.o.v[i].key; if (k.type != JVT_STR) return(-1); if ((*match)(&k.u.s)) { subrv = (*cb)(obj.u.o.v[i].val,cbarg); if (subrv < 0) return(subrv); rv += subrv; } } return(rv); } static JSON_VAL find_ret_common(JSON_VAL obj, int (*match)(const JSON_STR *)) { int i; JSON_VAL k; if (obj.type != JVT_OBJ) return(jval_err("argument isn't an object")); for (i=obj.u.o.n-1;i>=0;i--) { k = obj.u.o.v[i].key; if (k.type != JVT_STR) return(jval_err("object key isn't a string")); if ((*match)(&k.u.s)) return(obj.u.o.v[i].val); } return(jval_err("not found")); } static int string_match_ucp(const JSON_STR *k, const JSON_UCP *s, int l) { int i; if (k->len != l) return(0); if (k->flags & JSON_S_F_UNICODE) return(! bcmp(k->ucp,s,l*sizeof(JSON_UCP))); if (k->flags & JSON_S_F_ASCII) { for (i=l-1;i>=0;i--) { if (s[i] != k->ascii[i]) return(0); } return(1); } abort(); } static int string_match_ascii(const JSON_STR *k, const char *s, int l) { int i; if (k->len != l) return(0); if (k->flags & JSON_S_F_ASCII) return(! bcmp(k->ascii,s,l)); if (k->flags & JSON_S_F_UNICODE) { for (i=l-1;i>=0;i--) { if (s[i] != k->ucp[i]) return(0); } return(1); } abort(); } //////////////////////////////////////////////////////////////// // Exported APIs. JSON_VAL json_decode(JSON_UCP (*cb)(void *), void *cbarg, unsigned int flags) { PARSER p; p.ch = cb; p.arg = cbarg; p.flags = flags; pch(&p); return(parse(&p)); } JSON_VAL json_decode_ucp_len(const JSON_UCP *txt, int len, unsigned int flags) { DEC_UCP_LEN_PRIV p; p.txt = txt; p.len = len; p.x = 0; return(json_decode(&json_decode__ucp_len_cb,&p,flags)); } JSON_VAL json_decode_ascii(int (*cb)(void *), void *cbarg, unsigned int flags) { DEC_ASCII_CB_PRIV p; p.cb = cb; p.cbarg = cbarg; return(json_decode(&json_decode__ascii_cb,&p,flags)); } JSON_VAL json_decode_ascii_len(const char *txt, int len, unsigned int flags) { DEC_ASCII_LEN_PRIV p; p.txt = txt; p.len = len; p.x = 0; return(json_decode(&json_decode__ascii_len,&p,flags)); } JSON_VAL json_decode_ascii_nul(const char *txt, unsigned int flags) { return(json_decode(&json_decode__ascii_nul,&txt,flags)); } JSON_VAL json_decode_utf8(int (*cb)(void *), void *cbarg, unsigned int flags) { DEC_UTF8_CB_PRIV p; utf8_init(&p.c); p.cb = cb; p.cbarg = cbarg; return(json_decode(&json_decode__utf8_cb,&p,flags)); } JSON_VAL json_decode_utf8_len(const unsigned char *txt, int len, unsigned int flags) { DEC_UTF8_LEN_PRIV p; utf8_init(&p.c); p.txt = txt; p.len = len; p.x = 0; return(json_decode(&json_decode__utf8_len,&p,flags)); } JSON_VAL json_decode_utf8_nul(const unsigned char *txt, unsigned int flags) { DEC_UTF8_NUL_PRIV p; utf8_init(&p.c); p.txt = txt; p.x = 0; return(json_decode(&json_decode__utf8_nul,&p,flags)); } void json_val_drop(JSON_VAL v) { int i; switch (v.type) { case JVT_ERR: free(v.u.err); break; case JVT_EOF: break; case JVT_NULL: break; case JVT_BOOL: break; case JVT_NUM: break; case JVT_STR: if (v.u.s.flags & JSON_S_F_UNICODE) free(v.u.s.ucp); if (v.u.s.flags & JSON_S_F_ASCII) free(v.u.s.ascii); // if (v.u.s.flags & JSON_S_F_UTF8) free(v.u.s.utf8); break; case JVT_OBJ: for (i=v.u.o.n-1;i>=0;i--) { json_val_drop(v.u.o.v[i].key); json_val_drop(v.u.o.v[i].val); } free(v.u.o.v); break; case JVT_ARR: for (i=v.u.a.n-1;i>=0;i--) json_val_drop(v.u.a.v[i]); free(v.u.a.v); break; default: abort(); break; } } JSON_ENC_RV json_encode(JSON_VAL v, void (*cb)(JSON_UCP, void *), void *cbarg, unsigned int flags) { ENCODER e; e.cb = cb; e.cbarg = cbarg; e.flags = flags; return(encode(v,&e)); } JSON_ENC_RV json_encode_ascii(JSON_VAL v, void (*cb)(char, void *), void *cbarg, unsigned int flags) { ENCODER e; ENC_ASCII_PRIV p; p.cb = cb; p.cbarg = cbarg; e.cb = &enc_ascii_cb; e.cbarg = &p; e.flags = flags | JSON_API_ASCII; return(encode(v,&e)); } JSON_ENC_RV json_encode_utf8(JSON_VAL v, void (*cb)(unsigned char, void *), void *cbarg, unsigned int flags) { ENCODER e; ENC_UTF8_PRIV p; p.cb = cb; p.cbarg = cbarg; e.cb = &enc_utf8_cb; e.cbarg = &p; e.flags = flags; return(encode(v,&e)); } int json_obj_find_ucp_cb(JSON_VAL obj, const JSON_UCP *s, int sl, int (*cb)(JSON_VAL, void *), void *cbarg) { int match(const JSON_STR *k) { return(string_match_ucp(k,s,sl)); } return(find_cb_common(obj,cb,cbarg,&match)); } int json_obj_find_ascii_len_cb(JSON_VAL obj, const char *s, int sl, int (*cb)(JSON_VAL, void *), void *cbarg) { int match(const JSON_STR *k) { return(string_match_ascii(k,s,sl)); } return(find_cb_common(obj,cb,cbarg,&match)); } int json_obj_find_ascii_nul_cb(JSON_VAL obj, const char *s, int (*cb)(JSON_VAL, void *), void *cbarg) { int sl; int match(const JSON_STR *k) { return(string_match_ascii(k,s,sl)); } sl = strlen(s); return(find_cb_common(obj,cb,cbarg,&match)); } JSON_VAL json_obj_find_ucp_ret(JSON_VAL obj, const JSON_UCP *s, int sl) { int match(const JSON_STR *k) { return(string_match_ucp(k,s,sl)); } return(find_ret_common(obj,&match)); } JSON_VAL json_obj_find_ascii_len_ret(JSON_VAL obj, const char *s, int sl) { int match(const JSON_STR *k) { return(string_match_ascii(k,s,sl)); } return(find_ret_common(obj,&match)); } JSON_VAL json_obj_find_ascii_nul_ret(JSON_VAL obj, const char *s) { int sl; int match(const JSON_STR *k) { return(string_match_ascii(k,s,sl)); } sl = strlen(s); return(find_ret_common(obj,&match)); } JSON_VAL json_val_copy(const JSON_VAL v) { switch (v.type) { case JVT_ERR: return(jval_err("%s",v.u.err)); break; case JVT_EOF: case JVT_NULL: case JVT_BOOL: case JVT_NUM: return(v); break; case JVT_STR: { JSON_VAL n; n = jval_str(); n.u.s = v.u.s; if (n.u.s.flags & JSON_S_F_UNICODE) { n.u.s.ucp = malloc(n.u.s.len*sizeof(JSON_UCP)); bcopy(v.u.s.ucp,n.u.s.ucp,n.u.s.len*sizeof(JSON_UCP)); } if (n.u.s.flags & JSON_S_F_ASCII) { n.u.s.ascii = malloc(n.u.s.len); bcopy(v.u.s.ascii,n.u.s.ascii,n.u.s.len); } #if 0 if (n.u.s.flags & JSON_S_F_UTF8) { n.u.s.utf8 = malloc(n.u.s.utf8len); bcopy(v.u.s.utf8,n.u.s.utf8,n.u.s.utf8len); } #endif return(n); } break; case JVT_OBJ: { JSON_OBJENT *vec; int i; vec = malloc(v.u.o.n*sizeof(JSON_OBJENT)); for (i=v.u.o.n-1;i>=0;i--) { vec[i].key = json_val_copy(v.u.o.v[i].key); vec[i].val = json_val_copy(v.u.o.v[i].val); } return(jval_obj(v.u.o.n,vec)); } break; case JVT_ARR: { JSON_VAL *vec; int i; vec = malloc(v.u.a.n*sizeof(JSON_VAL)); for (i=v.u.a.n-1;i>=0;i--) vec[i] = json_val_copy(v.u.a.v[i]); return(jval_arr(v.u.a.n,vec)); } break; } return(jval_err("copying invalid type %d",(int)v.type)); } JSON_VAL json_val_err(const char *fmt, ...) { va_list ap; JSON_VAL v; va_start(ap,fmt); v = jval_err_v(fmt,ap); va_end(ap); return(v); } JSON_VAL json_val_eof(void) { return(jval_eof()); } JSON_VAL json_val_null(void) { return(jval_null()); } JSON_VAL json_val_bool(int b) { return(jval_bool(b)); } JSON_VAL json_val_num(double v) { return(jval_num(v)); } JSON_VAL json_val_str_ucp(JSON_UCP *s, int sl) { JSON_VAL v; v = jval_str(); v.u.s.flags |= JSON_S_F_UNICODE; v.u.s.len = sl; v.u.s.ucp = s; return(v); } JSON_VAL json_val_str_ucp_copy(const JSON_UCP *s, int sl) { JSON_VAL v; v = jval_str(); v.u.s.flags |= JSON_S_F_UNICODE; v.u.s.len = sl; v.u.s.ucp = malloc(sl*sizeof(JSON_UCP)); bcopy(s,v.u.s.ucp,sl*sizeof(JSON_UCP)); return(v); } JSON_VAL json_val_str_ascii_len(char *s, int sl) { JSON_VAL v; v = jval_str(); v.u.s.flags |= JSON_S_F_ASCII; v.u.s.len = sl; v.u.s.ascii = s; return(v); } JSON_VAL json_val_str_ascii_len_copy(const char *s, int sl) { JSON_VAL v; v = jval_str(); v.u.s.flags |= JSON_S_F_ASCII; v.u.s.len = sl; v.u.s.ascii = malloc(sl); bcopy(s,v.u.s.ascii,sl); return(v); } JSON_VAL json_val_str_ascii_nul(char *s) { JSON_VAL v; v = jval_str(); v.u.s.flags |= JSON_S_F_ASCII; v.u.s.len = strlen(s); v.u.s.ascii = s; return(v); } JSON_VAL json_val_str_ascii_nul_copy(const char *s) { JSON_VAL v; v = jval_str(); v.u.s.flags |= JSON_S_F_ASCII; v.u.s.len = strlen(s); v.u.s.ascii = malloc(v.u.s.len); bcopy(s,v.u.s.ascii,v.u.s.len); return(v); } JSON_VAL json_val_obj(JSON_OBJENT *vec, int len) { return(jval_obj(len,vec)); } JSON_VAL json_val_obj_copy(const JSON_OBJENT *vec, int len) { JSON_OBJENT *nv; int i; nv = malloc(len*sizeof(JSON_OBJENT)); for (i=len-1;i>=0;i--) { nv[i].key = json_val_copy(vec[i].key); nv[i].val = json_val_copy(vec[i].val); } return(jval_obj(len,nv)); } JSON_VAL json_val_arr(JSON_VAL *vec, int len) { return(jval_arr(len,vec)); } JSON_VAL json_val_arr_copy(const JSON_VAL *vec, int len) { JSON_VAL *nv; int i; nv = malloc(len*sizeof(JSON_VAL)); for (i=len-1;i>=0;i--) nv[i] = json_val_copy(vec[i]); return(jval_arr(len,nv)); } #ifdef TESTBED #include // Forward static void dump_json_val(JSON_VAL, FILE *); static void dump_json_str(JSON_STR s, FILE *f) { int i; JSON_UCP c; if (! (s.flags & JSON_S_F_UNICODE)) { fprintf(stderr,"...decoded string doesn't have UNICODE set\n"); abort(); } putc('"',f); for (i=0;i 126) fprintf(f,"«U%x»",c); else putc(c,f); } putc('"',f); } static void dump_json_obj(JSON_OBJENT *v, int n, FILE *f) { int i; putc('{'/*}*/,f); for (i=0;i 126)) return(JSON_UCP_ERR); return(c); } int main(void); int main(void) { JSON_VAL jv; jv = json_decode(&read_cb,0,0); dump_json_val(jv,stdout); printf("\n"); json_val_drop(jv); return(0); } #endif