1 18824b58 2008-08-03 rsc #include "a.h"
3 18824b58 2008-08-03 rsc static Json *parsevalue(char**);
6 18824b58 2008-08-03 rsc wskip(char *p)
8 18824b58 2008-08-03 rsc while(*p == ' ' || *p == '\t' || *p == '\n' || *p == '\v')
16 18824b58 2008-08-03 rsc return '0' <= c && c <= '9' ||
17 18824b58 2008-08-03 rsc 'a' <= c && c <= 'f' ||
18 18824b58 2008-08-03 rsc 'A' <= c && c <= 'F';
22 18824b58 2008-08-03 rsc newjval(int type)
26 18824b58 2008-08-03 rsc v = emalloc(sizeof *v);
28 18824b58 2008-08-03 rsc v->type = type;
33 18824b58 2008-08-03 rsc badjval(char **pp, char *fmt, ...)
35 18824b58 2008-08-03 rsc char buf[ERRMAX];
39 18824b58 2008-08-03 rsc va_start(arg, fmt);
40 18824b58 2008-08-03 rsc vsnprint(buf, sizeof buf, fmt, arg);
42 18824b58 2008-08-03 rsc errstr(buf, sizeof buf);
49 18824b58 2008-08-03 rsc _parsestring(char **pp, int *len)
51 18824b58 2008-08-03 rsc char *p, *q, *w, *s, *r;
55 18824b58 2008-08-03 rsc p = wskip(*pp);
56 18824b58 2008-08-03 rsc if(*p != '"'){
57 18824b58 2008-08-03 rsc badjval(pp, "missing opening quote for string");
60 18824b58 2008-08-03 rsc for(q=p+1; *q && *q != '\"'; q++){
61 18824b58 2008-08-03 rsc if(*q == '\\' && *(q+1) != 0)
63 18824b58 2008-08-03 rsc if((*q & 0xFF) < 0x20){ // no control chars
64 18824b58 2008-08-03 rsc badjval(pp, "control char in string");
69 18824b58 2008-08-03 rsc badjval(pp, "no closing quote in string");
72 18824b58 2008-08-03 rsc s = emalloc(q - p);
74 18824b58 2008-08-03 rsc for(r=p+1; r<q; ){
75 18824b58 2008-08-03 rsc if(*r != '\\'){
83 18824b58 2008-08-03 rsc badjval(pp, "bad escape \\%c in string", *r&0xFF);
103 18824b58 2008-08-03 rsc *w++ = '\r';
107 18824b58 2008-08-03 rsc *w++ = '\t';
112 18824b58 2008-08-03 rsc if(!ishex(r[0]) || !ishex(r[1]) || !ishex(r[2]) || !ishex(r[3])){
114 18824b58 2008-08-03 rsc badjval(pp, "bad hex \\u%.4s", r);
117 18824b58 2008-08-03 rsc memmove(buf, r, 4);
119 18824b58 2008-08-03 rsc rune = strtol(buf, 0, 16);
120 18824b58 2008-08-03 rsc if(rune == 0){
122 18824b58 2008-08-03 rsc badjval(pp, "\\u0000 in string");
126 18824b58 2008-08-03 rsc w += runetochar(w, &rune);
132 18824b58 2008-08-03 rsc *len = w - s;
137 18824b58 2008-08-03 rsc static Json*
138 18824b58 2008-08-03 rsc parsenumber(char **pp)
140 18824b58 2008-08-03 rsc char *p, *q;
145 18824b58 2008-08-03 rsc /* -?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([Ee][-+]?[0-9]+) */
146 18824b58 2008-08-03 rsc p = wskip(*pp);
148 18824b58 2008-08-03 rsc if(*q == '-')
150 18824b58 2008-08-03 rsc if(*q == '0')
153 18824b58 2008-08-03 rsc if(*q < '1' || *q > '9')
154 18824b58 2008-08-03 rsc return badjval(pp, "invalid number");
155 18824b58 2008-08-03 rsc while('0' <= *q && *q <= '9')
158 18824b58 2008-08-03 rsc if(*q == '.'){
160 18824b58 2008-08-03 rsc if(*q < '0' || *q > '9')
161 18824b58 2008-08-03 rsc return badjval(pp, "invalid number");
162 18824b58 2008-08-03 rsc while('0' <= *q && *q <= '9')
165 18824b58 2008-08-03 rsc if(*q == 'e' || *q == 'E'){
167 18824b58 2008-08-03 rsc if(*q == '-' || *q == '+')
169 18824b58 2008-08-03 rsc if(*q < '0' || *q > '9')
170 18824b58 2008-08-03 rsc return badjval(pp, "invalid number");
171 18824b58 2008-08-03 rsc while('0' <= *q && *q <= '9')
175 18824b58 2008-08-03 rsc t = emalloc(q-p+1);
176 18824b58 2008-08-03 rsc memmove(t, p, q-p);
179 18824b58 2008-08-03 rsc d = strtod(t, nil);
180 18824b58 2008-08-03 rsc if(errno != 0){
182 18824b58 2008-08-03 rsc return badjval(pp, nil);
185 18824b58 2008-08-03 rsc v = newjval(Jnumber);
186 18824b58 2008-08-03 rsc v->number = d;
191 18824b58 2008-08-03 rsc static Json*
192 18824b58 2008-08-03 rsc parsestring(char **pp)
198 18824b58 2008-08-03 rsc s = _parsestring(pp, &len);
199 18824b58 2008-08-03 rsc if(s == nil)
201 18824b58 2008-08-03 rsc v = newjval(Jstring);
202 18824b58 2008-08-03 rsc v->string = s;
203 18824b58 2008-08-03 rsc v->len = len;
207 18824b58 2008-08-03 rsc static Json*
208 18824b58 2008-08-03 rsc parsename(char **pp)
210 18824b58 2008-08-03 rsc if(strncmp(*pp, "true", 4) == 0){
212 18824b58 2008-08-03 rsc return newjval(Jtrue);
214 18824b58 2008-08-03 rsc if(strncmp(*pp, "false", 5) == 0){
216 18824b58 2008-08-03 rsc return newjval(Jfalse);
218 18824b58 2008-08-03 rsc if(strncmp(*pp, "null", 4) == 0){
220 18824b58 2008-08-03 rsc return newjval(Jtrue);
222 18824b58 2008-08-03 rsc return badjval(pp, "invalid name");
225 18824b58 2008-08-03 rsc static Json*
226 18824b58 2008-08-03 rsc parsearray(char **pp)
232 18824b58 2008-08-03 rsc if(*p++ != '[')
233 18824b58 2008-08-03 rsc return badjval(pp, "missing bracket for array");
234 18824b58 2008-08-03 rsc v = newjval(Jarray);
235 18824b58 2008-08-03 rsc p = wskip(p);
236 18824b58 2008-08-03 rsc if(*p != ']'){
238 18824b58 2008-08-03 rsc if(v->len%32 == 0)
239 18824b58 2008-08-03 rsc v->value = erealloc(v->value, (v->len+32)*sizeof v->value[0]);
240 18824b58 2008-08-03 rsc if((v->value[v->len++] = parsevalue(&p)) == nil){
242 18824b58 2008-08-03 rsc return badjval(pp, nil);
244 18824b58 2008-08-03 rsc p = wskip(p);
245 18824b58 2008-08-03 rsc if(*p == ']')
247 18824b58 2008-08-03 rsc if(*p++ != ','){
249 18824b58 2008-08-03 rsc return badjval(pp, "missing comma in array");
258 18824b58 2008-08-03 rsc static Json*
259 18824b58 2008-08-03 rsc parseobject(char **pp)
265 18824b58 2008-08-03 rsc if(*p++ != '{')
266 18824b58 2008-08-03 rsc return badjval(pp, "missing brace for object");
267 18824b58 2008-08-03 rsc v = newjval(Jobject);
268 18824b58 2008-08-03 rsc p = wskip(p);
269 18824b58 2008-08-03 rsc if(*p != '}'){
271 18824b58 2008-08-03 rsc if(v->len%32 == 0){
272 18824b58 2008-08-03 rsc v->name = erealloc(v->name, (v->len+32)*sizeof v->name[0]);
273 18824b58 2008-08-03 rsc v->value = erealloc(v->value, (v->len+32)*sizeof v->value[0]);
275 18824b58 2008-08-03 rsc if((v->name[v->len++] = _parsestring(&p, nil)) == nil){
277 18824b58 2008-08-03 rsc return badjval(pp, nil);
279 18824b58 2008-08-03 rsc p = wskip(p);
280 18824b58 2008-08-03 rsc if(*p++ != ':'){
282 18824b58 2008-08-03 rsc return badjval(pp, "missing colon in object");
284 18824b58 2008-08-03 rsc if((v->value[v->len-1] = parsevalue(&p)) == nil){
286 18824b58 2008-08-03 rsc return badjval(pp, nil);
288 18824b58 2008-08-03 rsc p = wskip(p);
289 18824b58 2008-08-03 rsc if(*p == '}')
291 18824b58 2008-08-03 rsc if(*p++ != ','){
293 18824b58 2008-08-03 rsc return badjval(pp, "missing comma in object");
302 18824b58 2008-08-03 rsc static Json*
303 18824b58 2008-08-03 rsc parsevalue(char **pp)
305 18824b58 2008-08-03 rsc *pp = wskip(*pp);
306 18824b58 2008-08-03 rsc switch(**pp){
318 18824b58 2008-08-03 rsc return parsenumber(pp);
322 18824b58 2008-08-03 rsc return parsename(pp);
324 18824b58 2008-08-03 rsc return parsestring(pp);
326 18824b58 2008-08-03 rsc return parsearray(pp);
328 18824b58 2008-08-03 rsc return parseobject(pp);
330 18824b58 2008-08-03 rsc return badjval(pp, "unexpected char <%02x>", **pp & 0xFF);
335 18824b58 2008-08-03 rsc parsejson(char *text)
339 18824b58 2008-08-03 rsc v = parsevalue(&text);
340 18824b58 2008-08-03 rsc if(v && text && *wskip(text) != 0){
342 18824b58 2008-08-03 rsc werrstr("extra data in json");
349 18824b58 2008-08-03 rsc _printjval(Fmt *fmt, Json *v, int n)
353 18824b58 2008-08-03 rsc if(v == nil){
354 18824b58 2008-08-03 rsc fmtprint(fmt, "nil");
357 18824b58 2008-08-03 rsc switch(v->type){
358 18824b58 2008-08-03 rsc case Jstring:
359 18824b58 2008-08-03 rsc fmtprint(fmt, "\"%s\"", v->string);
361 18824b58 2008-08-03 rsc case Jnumber:
362 18824b58 2008-08-03 rsc if(floor(v->number) == v->number)
363 18824b58 2008-08-03 rsc fmtprint(fmt, "%.0f", v->number);
365 18824b58 2008-08-03 rsc fmtprint(fmt, "%g", v->number);
367 18824b58 2008-08-03 rsc case Jobject:
368 18824b58 2008-08-03 rsc fmtprint(fmt, "{");
371 18824b58 2008-08-03 rsc for(i=0; i<v->len; i++){
373 18824b58 2008-08-03 rsc fmtprint(fmt, "\n%*s", n*4, "");
374 18824b58 2008-08-03 rsc fmtprint(fmt, "\"%s\" : ", v->name[i]);
375 18824b58 2008-08-03 rsc _printjval(fmt, v->value[i], n);
376 18824b58 2008-08-03 rsc fmtprint(fmt, ",");
380 18824b58 2008-08-03 rsc if(v->len > 0)
381 18824b58 2008-08-03 rsc fmtprint(fmt, "\n%*s", n*4);
383 18824b58 2008-08-03 rsc fmtprint(fmt, "}");
385 18824b58 2008-08-03 rsc case Jarray:
386 18824b58 2008-08-03 rsc fmtprint(fmt, "[");
389 18824b58 2008-08-03 rsc for(i=0; i<v->len; i++){
391 18824b58 2008-08-03 rsc fmtprint(fmt, "\n%*s", n*4, "");
392 18824b58 2008-08-03 rsc _printjval(fmt, v->value[i], n);
393 18824b58 2008-08-03 rsc fmtprint(fmt, ",");
397 18824b58 2008-08-03 rsc if(v->len > 0)
398 18824b58 2008-08-03 rsc fmtprint(fmt, "\n%*s", n*4);
400 18824b58 2008-08-03 rsc fmtprint(fmt, "]");
403 18824b58 2008-08-03 rsc fmtprint(fmt, "true");
405 18824b58 2008-08-03 rsc case Jfalse:
406 18824b58 2008-08-03 rsc fmtprint(fmt, "false");
409 18824b58 2008-08-03 rsc fmtprint(fmt, "null");
416 18824b58 2008-08-03 rsc printjval(Json *v)
419 18824b58 2008-08-03 rsc char buf[256];
421 18824b58 2008-08-03 rsc fmtfdinit(&fmt, 1, buf, sizeof buf);
422 18824b58 2008-08-03 rsc _printjval(&fmt, v, 0);
423 18824b58 2008-08-03 rsc fmtprint(&fmt, "\n");
424 18824b58 2008-08-03 rsc fmtfdflush(&fmt);
429 18824b58 2008-08-03 rsc jsonfmt(Fmt *fmt)
433 18824b58 2008-08-03 rsc v = va_arg(fmt->args, Json*);
434 18824b58 2008-08-03 rsc if(fmt->flags&FmtSharp)
435 18824b58 2008-08-03 rsc _printjval(fmt, v, 0);
437 18824b58 2008-08-03 rsc _printjval(fmt, v, -1);
442 18824b58 2008-08-03 rsc jincref(Json *v)
444 18824b58 2008-08-03 rsc if(v == nil)
451 18824b58 2008-08-03 rsc jclose(Json *v)
455 18824b58 2008-08-03 rsc if(v == nil)
457 18824b58 2008-08-03 rsc if(--v->ref > 0)
459 18824b58 2008-08-03 rsc if(v->ref < 0)
460 18824b58 2008-08-03 rsc sysfatal("jclose: ref %d", v->ref);
462 18824b58 2008-08-03 rsc switch(v->type){
463 18824b58 2008-08-03 rsc case Jstring:
464 18824b58 2008-08-03 rsc free(v->string);
466 18824b58 2008-08-03 rsc case Jarray:
467 18824b58 2008-08-03 rsc for(i=0; i<v->len; i++)
468 18824b58 2008-08-03 rsc jclose(v->value[i]);
469 18824b58 2008-08-03 rsc free(v->value);
471 18824b58 2008-08-03 rsc case Jobject:
472 18824b58 2008-08-03 rsc for(i=0; i<v->len; i++){
473 18824b58 2008-08-03 rsc free(v->name[i]);
474 18824b58 2008-08-03 rsc jclose(v->value[i]);
476 18824b58 2008-08-03 rsc free(v->value);
477 18824b58 2008-08-03 rsc free(v->name);
484 18824b58 2008-08-03 rsc jlookup(Json *v, char *name)
488 18824b58 2008-08-03 rsc if(v->type != Jobject)
490 18824b58 2008-08-03 rsc for(i=0; i<v->len; i++)
491 18824b58 2008-08-03 rsc if(strcmp(v->name[i], name) == 0)
492 18824b58 2008-08-03 rsc return v->value[i];
497 18824b58 2008-08-03 rsc jwalk(Json *v, char *path)
499 18824b58 2008-08-03 rsc char elem[128], *p, *next;
502 18824b58 2008-08-03 rsc for(p=path; *p && v; p=next){
503 18824b58 2008-08-03 rsc next = strchr(p, '/');
504 18824b58 2008-08-03 rsc if(next == nil)
505 18824b58 2008-08-03 rsc next = p+strlen(p);
506 18824b58 2008-08-03 rsc if(next-p >= sizeof elem)
507 18824b58 2008-08-03 rsc sysfatal("jwalk path elem too long - %s", path);
508 18824b58 2008-08-03 rsc memmove(elem, p, next-p);
509 18824b58 2008-08-03 rsc elem[next-p] = 0;
510 18824b58 2008-08-03 rsc if(*next == '/')
512 18824b58 2008-08-03 rsc if(v->type == Jarray && *elem && (n=strtol(elem, &p, 10)) >= 0 && *p == 0){
513 18824b58 2008-08-03 rsc if(n >= v->len)
515 18824b58 2008-08-03 rsc v = v->value[n];
517 18824b58 2008-08-03 rsc v = jlookup(v, elem);
523 18824b58 2008-08-03 rsc jstring(Json *jv)
525 18824b58 2008-08-03 rsc if(jv == nil || jv->type != Jstring)
527 18824b58 2008-08-03 rsc return jv->string;
531 18824b58 2008-08-03 rsc jint(Json *jv)
533 18824b58 2008-08-03 rsc if(jv == nil || jv->type != Jnumber)
535 18824b58 2008-08-03 rsc return jv->number;
539 18824b58 2008-08-03 rsc jnumber(Json *jv)
541 18824b58 2008-08-03 rsc if(jv == nil || jv->type != Jnumber)
543 18824b58 2008-08-03 rsc return jv->number;
547 18824b58 2008-08-03 rsc jstrcmp(Json *jv, char *s)
551 18824b58 2008-08-03 rsc t = jstring(jv);
552 18824b58 2008-08-03 rsc if(t == nil)
554 18824b58 2008-08-03 rsc return strcmp(t, s);