json.c (8526B)
1 #include "a.h" 2 3 static Json *parsevalue(char**); 4 5 static char* 6 wskip(char *p) 7 { 8 while(*p == ' ' || *p == '\t' || *p == '\n' || *p == '\v') 9 p++; 10 return p; 11 } 12 13 static int 14 ishex(int c) 15 { 16 return '0' <= c && c <= '9' || 17 'a' <= c && c <= 'f' || 18 'A' <= c && c <= 'F'; 19 } 20 21 static Json* 22 newjval(int type) 23 { 24 Json *v; 25 26 v = emalloc(sizeof *v); 27 v->ref = 1; 28 v->type = type; 29 return v; 30 } 31 32 static Json* 33 badjval(char **pp, char *fmt, ...) 34 { 35 char buf[ERRMAX]; 36 va_list arg; 37 38 if(fmt){ 39 va_start(arg, fmt); 40 vsnprint(buf, sizeof buf, fmt, arg); 41 va_end(arg); 42 errstr(buf, sizeof buf); 43 } 44 *pp = nil; 45 return nil; 46 } 47 48 static char* 49 _parsestring(char **pp, int *len) 50 { 51 char *p, *q, *w, *s, *r; 52 char buf[5]; 53 Rune rune; 54 55 p = wskip(*pp); 56 if(*p != '"'){ 57 badjval(pp, "missing opening quote for string"); 58 return nil; 59 } 60 for(q=p+1; *q && *q != '\"'; q++){ 61 if(*q == '\\' && *(q+1) != 0) 62 q++; 63 if((*q & 0xFF) < 0x20){ // no control chars 64 badjval(pp, "control char in string"); 65 return nil; 66 } 67 } 68 if(*q == 0){ 69 badjval(pp, "no closing quote in string"); 70 return nil; 71 } 72 s = emalloc(q - p); 73 w = s; 74 for(r=p+1; r<q; ){ 75 if(*r != '\\'){ 76 *w++ = *r++; 77 continue; 78 } 79 r++; 80 switch(*r){ 81 default: 82 free(s); 83 badjval(pp, "bad escape \\%c in string", *r&0xFF); 84 return nil; 85 case '\\': 86 case '\"': 87 case '/': 88 *w++ = *r++; 89 break; 90 case 'b': 91 *w++ = '\b'; 92 r++; 93 break; 94 case 'f': 95 *w++ = '\f'; 96 r++; 97 break; 98 case 'n': 99 *w++ = '\n'; 100 r++; 101 break; 102 case 'r': 103 *w++ = '\r'; 104 r++; 105 break; 106 case 't': 107 *w++ = '\t'; 108 r++; 109 break; 110 case 'u': 111 r++; 112 if(!ishex(r[0]) || !ishex(r[1]) || !ishex(r[2]) || !ishex(r[3])){ 113 free(s); 114 badjval(pp, "bad hex \\u%.4s", r); 115 return nil; 116 } 117 memmove(buf, r, 4); 118 buf[4] = 0; 119 rune = strtol(buf, 0, 16); 120 if(rune == 0){ 121 free(s); 122 badjval(pp, "\\u0000 in string"); 123 return nil; 124 } 125 r += 4; 126 w += runetochar(w, &rune); 127 break; 128 } 129 } 130 *w = 0; 131 if(len) 132 *len = w - s; 133 *pp = q+1; 134 return s; 135 } 136 137 static Json* 138 parsenumber(char **pp) 139 { 140 char *p, *q; 141 char *t; 142 double d; 143 Json *v; 144 145 /* -?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([Ee][-+]?[0-9]+) */ 146 p = wskip(*pp); 147 q = p; 148 if(*q == '-') 149 q++; 150 if(*q == '0') 151 q++; 152 else{ 153 if(*q < '1' || *q > '9') 154 return badjval(pp, "invalid number"); 155 while('0' <= *q && *q <= '9') 156 q++; 157 } 158 if(*q == '.'){ 159 q++; 160 if(*q < '0' || *q > '9') 161 return badjval(pp, "invalid number"); 162 while('0' <= *q && *q <= '9') 163 q++; 164 } 165 if(*q == 'e' || *q == 'E'){ 166 q++; 167 if(*q == '-' || *q == '+') 168 q++; 169 if(*q < '0' || *q > '9') 170 return badjval(pp, "invalid number"); 171 while('0' <= *q && *q <= '9') 172 q++; 173 } 174 175 t = emalloc(q-p+1); 176 memmove(t, p, q-p); 177 t[q-p] = 0; 178 errno = 0; 179 d = strtod(t, nil); 180 if(errno != 0){ 181 free(t); 182 return badjval(pp, nil); 183 } 184 free(t); 185 v = newjval(Jnumber); 186 v->number = d; 187 *pp = q; 188 return v; 189 } 190 191 static Json* 192 parsestring(char **pp) 193 { 194 char *s; 195 Json *v; 196 int len; 197 198 s = _parsestring(pp, &len); 199 if(s == nil) 200 return nil; 201 v = newjval(Jstring); 202 v->string = s; 203 v->len = len; 204 return v; 205 } 206 207 static Json* 208 parsename(char **pp) 209 { 210 if(strncmp(*pp, "true", 4) == 0){ 211 *pp += 4; 212 return newjval(Jtrue); 213 } 214 if(strncmp(*pp, "false", 5) == 0){ 215 *pp += 5; 216 return newjval(Jfalse); 217 } 218 if(strncmp(*pp, "null", 4) == 0){ 219 *pp += 4; 220 return newjval(Jtrue); 221 } 222 return badjval(pp, "invalid name"); 223 } 224 225 static Json* 226 parsearray(char **pp) 227 { 228 char *p; 229 Json *v; 230 231 p = *pp; 232 if(*p++ != '[') 233 return badjval(pp, "missing bracket for array"); 234 v = newjval(Jarray); 235 p = wskip(p); 236 if(*p != ']'){ 237 for(;;){ 238 if(v->len%32 == 0) 239 v->value = erealloc(v->value, (v->len+32)*sizeof v->value[0]); 240 if((v->value[v->len++] = parsevalue(&p)) == nil){ 241 jclose(v); 242 return badjval(pp, nil); 243 } 244 p = wskip(p); 245 if(*p == ']') 246 break; 247 if(*p++ != ','){ 248 jclose(v); 249 return badjval(pp, "missing comma in array"); 250 } 251 } 252 } 253 p++; 254 *pp = p; 255 return v; 256 } 257 258 static Json* 259 parseobject(char **pp) 260 { 261 char *p; 262 Json *v; 263 264 p = *pp; 265 if(*p++ != '{') 266 return badjval(pp, "missing brace for object"); 267 v = newjval(Jobject); 268 p = wskip(p); 269 if(*p != '}'){ 270 for(;;){ 271 if(v->len%32 == 0){ 272 v->name = erealloc(v->name, (v->len+32)*sizeof v->name[0]); 273 v->value = erealloc(v->value, (v->len+32)*sizeof v->value[0]); 274 } 275 if((v->name[v->len++] = _parsestring(&p, nil)) == nil){ 276 jclose(v); 277 return badjval(pp, nil); 278 } 279 p = wskip(p); 280 if(*p++ != ':'){ 281 jclose(v); 282 return badjval(pp, "missing colon in object"); 283 } 284 if((v->value[v->len-1] = parsevalue(&p)) == nil){ 285 jclose(v); 286 return badjval(pp, nil); 287 } 288 p = wskip(p); 289 if(*p == '}') 290 break; 291 if(*p++ != ','){ 292 jclose(v); 293 return badjval(pp, "missing comma in object"); 294 } 295 } 296 } 297 p++; 298 *pp = p; 299 return v; 300 } 301 302 static Json* 303 parsevalue(char **pp) 304 { 305 *pp = wskip(*pp); 306 switch(**pp){ 307 case '0': 308 case '1': 309 case '2': 310 case '3': 311 case '4': 312 case '5': 313 case '6': 314 case '7': 315 case '8': 316 case '9': 317 case '-': 318 return parsenumber(pp); 319 case 't': 320 case 'f': 321 case 'n': 322 return parsename(pp); 323 case '\"': 324 return parsestring(pp); 325 case '[': 326 return parsearray(pp); 327 case '{': 328 return parseobject(pp); 329 default: 330 return badjval(pp, "unexpected char <%02x>", **pp & 0xFF); 331 } 332 } 333 334 Json* 335 parsejson(char *text) 336 { 337 Json *v; 338 339 v = parsevalue(&text); 340 if(v && text && *wskip(text) != 0){ 341 jclose(v); 342 werrstr("extra data in json"); 343 return nil; 344 } 345 return v; 346 } 347 348 void 349 _printjval(Fmt *fmt, Json *v, int n) 350 { 351 int i; 352 353 if(v == nil){ 354 fmtprint(fmt, "nil"); 355 return; 356 } 357 switch(v->type){ 358 case Jstring: 359 fmtprint(fmt, "\"%s\"", v->string); 360 break; 361 case Jnumber: 362 if(floor(v->number) == v->number) 363 fmtprint(fmt, "%.0f", v->number); 364 else 365 fmtprint(fmt, "%g", v->number); 366 break; 367 case Jobject: 368 fmtprint(fmt, "{"); 369 if(n >= 0) 370 n++; 371 for(i=0; i<v->len; i++){ 372 if(n > 0) 373 fmtprint(fmt, "\n%*s", n*4, ""); 374 fmtprint(fmt, "\"%s\" : ", v->name[i]); 375 _printjval(fmt, v->value[i], n); 376 fmtprint(fmt, ","); 377 } 378 if(n > 0){ 379 n--; 380 if(v->len > 0) 381 fmtprint(fmt, "\n%*s", n*4); 382 } 383 fmtprint(fmt, "}"); 384 break; 385 case Jarray: 386 fmtprint(fmt, "["); 387 if(n >= 0) 388 n++; 389 for(i=0; i<v->len; i++){ 390 if(n > 0) 391 fmtprint(fmt, "\n%*s", n*4, ""); 392 _printjval(fmt, v->value[i], n); 393 fmtprint(fmt, ","); 394 } 395 if(n > 0){ 396 n--; 397 if(v->len > 0) 398 fmtprint(fmt, "\n%*s", n*4); 399 } 400 fmtprint(fmt, "]"); 401 break; 402 case Jtrue: 403 fmtprint(fmt, "true"); 404 break; 405 case Jfalse: 406 fmtprint(fmt, "false"); 407 break; 408 case Jnull: 409 fmtprint(fmt, "null"); 410 break; 411 } 412 } 413 414 /* 415 void 416 printjval(Json *v) 417 { 418 Fmt fmt; 419 char buf[256]; 420 421 fmtfdinit(&fmt, 1, buf, sizeof buf); 422 _printjval(&fmt, v, 0); 423 fmtprint(&fmt, "\n"); 424 fmtfdflush(&fmt); 425 } 426 */ 427 428 int 429 jsonfmt(Fmt *fmt) 430 { 431 Json *v; 432 433 v = va_arg(fmt->args, Json*); 434 if(fmt->flags&FmtSharp) 435 _printjval(fmt, v, 0); 436 else 437 _printjval(fmt, v, -1); 438 return 0; 439 } 440 441 Json* 442 jincref(Json *v) 443 { 444 if(v == nil) 445 return nil; 446 ++v->ref; 447 return v; 448 } 449 450 void 451 jclose(Json *v) 452 { 453 int i; 454 455 if(v == nil) 456 return; 457 if(--v->ref > 0) 458 return; 459 if(v->ref < 0) 460 sysfatal("jclose: ref %d", v->ref); 461 462 switch(v->type){ 463 case Jstring: 464 free(v->string); 465 break; 466 case Jarray: 467 for(i=0; i<v->len; i++) 468 jclose(v->value[i]); 469 free(v->value); 470 break; 471 case Jobject: 472 for(i=0; i<v->len; i++){ 473 free(v->name[i]); 474 jclose(v->value[i]); 475 } 476 free(v->value); 477 free(v->name); 478 break; 479 } 480 free(v); 481 } 482 483 Json* 484 jlookup(Json *v, char *name) 485 { 486 int i; 487 488 if(v->type != Jobject) 489 return nil; 490 for(i=0; i<v->len; i++) 491 if(strcmp(v->name[i], name) == 0) 492 return v->value[i]; 493 return nil; 494 } 495 496 Json* 497 jwalk(Json *v, char *path) 498 { 499 char elem[128], *p, *next; 500 int n; 501 502 for(p=path; *p && v; p=next){ 503 next = strchr(p, '/'); 504 if(next == nil) 505 next = p+strlen(p); 506 if(next-p >= sizeof elem) 507 sysfatal("jwalk path elem too long - %s", path); 508 memmove(elem, p, next-p); 509 elem[next-p] = 0; 510 if(*next == '/') 511 next++; 512 if(v->type == Jarray && *elem && (n=strtol(elem, &p, 10)) >= 0 && *p == 0){ 513 if(n >= v->len) 514 return nil; 515 v = v->value[n]; 516 }else 517 v = jlookup(v, elem); 518 } 519 return v; 520 } 521 522 char* 523 jstring(Json *jv) 524 { 525 if(jv == nil || jv->type != Jstring) 526 return nil; 527 return jv->string; 528 } 529 530 vlong 531 jint(Json *jv) 532 { 533 if(jv == nil || jv->type != Jnumber) 534 return -1; 535 return jv->number; 536 } 537 538 double 539 jnumber(Json *jv) 540 { 541 if(jv == nil || jv->type != Jnumber) 542 return 0; 543 return jv->number; 544 } 545 546 int 547 jstrcmp(Json *jv, char *s) 548 { 549 char *t; 550 551 t = jstring(jv); 552 if(t == nil) 553 return -2; 554 return strcmp(t, s); 555 }