1 /* 2 * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org> 3 * 4 * Jansson is free software; you can redistribute it and/or modify 5 * it under the terms of the MIT license. See LICENSE for details. 6 */ 7 /** 8 * License: MIT 9 */ 10 module jansson_d.load; 11 12 13 package: 14 15 private static import core.stdc.errno; 16 private static import core.stdc.stdio; 17 private static import core.stdc.stdlib; 18 private static import core.stdc.string; 19 private static import core.sys.posix.unistd; 20 private static import jansson_d.jansson; 21 private static import jansson_d.jansson_config; 22 private static import jansson_d.jansson_private; 23 private static import jansson_d.strbuffer; 24 private static import jansson_d.utf; 25 private static import jansson_d.value; 26 27 enum STREAM_STATE_OK = 0; 28 enum STREAM_STATE_EOF = -1; 29 enum STREAM_STATE_ERROR = -2; 30 31 enum TOKEN_INVALID = -1; 32 enum TOKEN_EOF = 0; 33 enum TOKEN_STRING = 256; 34 enum TOKEN_INTEGER = 257; 35 enum TOKEN_REAL = 258; 36 enum TOKEN_TRUE = 259; 37 enum TOKEN_FALSE = 260; 38 enum TOKEN_NULL = 261; 39 40 /* Locale independent versions of isxxx() functions */ 41 private template l_isupper(string c) 42 { 43 enum l_isupper = "(('A' <= (c)) && ((c) <= 'Z'))"; 44 } 45 46 private template l_islower(string c) 47 { 48 enum l_islower = "(('a' <= (c)) && ((c) <= 'z'))"; 49 } 50 51 private template l_isalpha(string c) 52 { 53 enum l_isalpha = "((mixin (jansson_d.load.l_isupper!(\"" ~ c ~ "\"))) || (mixin (jansson_d.load.l_islower!(\"" ~ c ~ "\"))))"; 54 } 55 56 private template l_isdigit(string c) 57 { 58 enum l_isdigit = "(('0' <= (c)) && ((c) <= '9'))"; 59 } 60 61 private template l_isxdigit(string c) 62 { 63 enum l_isxdigit = "((mixin (jansson_d.load.l_isdigit!(\"" ~ c ~ "\"))) || (('A' <= (c)) && ((c) <= 'F')) || (('a' <= (c)) && ((c) <= 'f')))"; 64 } 65 66 /* 67 * Read one byte from stream, convert to ubyte, then int, and 68 * return. return EOF on end of file. This corresponds to the 69 * behaviour of fgetc(). 70 */ 71 alias get_func = extern (C) nothrow @nogc @live int function(scope void* data); 72 73 struct stream_t 74 { 75 .get_func get; 76 void* data; 77 char[5] buffer = '\0'; 78 size_t buffer_pos; 79 int state; 80 int line; 81 int column; 82 int last_column; 83 size_t position; 84 } 85 86 struct lex_t 87 { 88 .stream_t stream; 89 jansson_d.strbuffer.strbuffer_t saved_text; 90 size_t flags; 91 size_t depth; 92 int token; 93 94 union value_ 95 { 96 struct string__ 97 { 98 char* val; 99 size_t len; 100 } 101 102 string__ string_; 103 jansson_d.jansson.json_int_t integer; 104 double real_; 105 } 106 107 value_ value; 108 } 109 110 private template stream_to_lex(string stream) 111 { 112 enum stream_to_lex = "(mixin (jansson_d.jansson_private.container_of!(\"" ~ stream ~ "\", \"jansson_d.load.lex_t\", \"stream\")))"; 113 } 114 115 /* error reporting */ 116 nothrow @trusted @nogc @live 117 private void error_set(F ...)(scope jansson_d.jansson.json_error_t* error, scope const .lex_t* lex, jansson_d.jansson.json_error_code_t code, scope const char* msg, F f) 118 119 do 120 { 121 char[jansson_d.jansson.JSON_ERROR_TEXT_LENGTH] msg_text = void; 122 char[jansson_d.jansson.JSON_ERROR_TEXT_LENGTH] msg_with_context = void; 123 124 int line = -1; 125 int col = -1; 126 size_t pos = 0; 127 const (char)* result = &(msg_text[0]); 128 129 if (error == null) { 130 return; 131 } 132 133 static if (f.length != 0) { 134 jansson_d.jansson_private.snprintf(&(msg_text[0]), msg_text.length, msg, f[0 .. $]); 135 } else { 136 jansson_d.jansson_private.snprintf(&(msg_text[0]), msg_text.length, msg); 137 } 138 139 msg_text[msg_text.length - 1] = '\0'; 140 141 if (lex != null) { 142 const char* saved_text = jansson_d.strbuffer.strbuffer_value(&lex.saved_text); 143 144 line = lex.stream.line; 145 col = lex.stream.column; 146 pos = lex.stream.position; 147 148 if ((saved_text != null) && (saved_text[0])) { 149 if (lex.saved_text.length_ <= 20) { 150 jansson_d.jansson_private.snprintf(&(msg_with_context[0]), msg_with_context.length, "%s near '%s'", &(msg_text[0]), saved_text); 151 msg_with_context[msg_with_context.length - 1] = '\0'; 152 result = &(msg_with_context[0]); 153 } 154 } else { 155 if (code == jansson_d.jansson.json_error_code_t.json_error_invalid_syntax) { 156 /* More specific error code for premature end of file. */ 157 code = jansson_d.jansson.json_error_code_t.json_error_premature_end_of_input; 158 } 159 160 if (lex.stream.state == .STREAM_STATE_ERROR) { 161 /* No context for UTF-8 decoding errors */ 162 result = &(msg_text[0]); 163 } else { 164 jansson_d.jansson_private.snprintf(&(msg_with_context[0]), msg_with_context.length, "%s near end of file", &(msg_text[0])); 165 msg_with_context[msg_with_context.length - 1] = '\0'; 166 result = &(msg_with_context[0]); 167 } 168 } 169 } 170 171 jansson_d.jansson_private.jsonp_error_set(error, line, col, pos, code, "%s", result); 172 } 173 174 /* lexical analyzer */ 175 176 pure nothrow @trusted @nogc @live 177 private void stream_init(scope .stream_t* stream, .get_func get, scope void* data) 178 179 in 180 { 181 assert(stream != null); 182 } 183 184 do 185 { 186 stream.get = get; 187 stream.data = data; 188 stream.buffer[0] = '\0'; 189 stream.buffer_pos = 0; 190 191 stream.state = .STREAM_STATE_OK; 192 stream.line = 1; 193 stream.column = 0; 194 stream.position = 0; 195 } 196 197 nothrow @nogc @live 198 private int stream_get(scope .stream_t* stream, scope jansson_d.jansson.json_error_t* error) 199 200 in 201 { 202 assert(stream != null); 203 } 204 205 do 206 { 207 if (stream.state != .STREAM_STATE_OK) { 208 return stream.state; 209 } 210 211 int c = void; 212 213 if (!stream.buffer[stream.buffer_pos]) { 214 assert(stream.get != null); 215 c = stream.get(stream.data); 216 217 if (c == core.stdc.stdio.EOF) { 218 stream.state = .STREAM_STATE_EOF; 219 220 return .STREAM_STATE_EOF; 221 } 222 223 stream.buffer[0] = cast(char)(c); 224 stream.buffer_pos = 0; 225 226 if ((0x80 <= c) && (c <= 0xFF)) { 227 /* multi-byte UTF-8 sequence */ 228 229 size_t count = jansson_d.utf.utf8_check_first(cast(char)(c)); 230 231 if (count == 0) { 232 goto out_; 233 } 234 235 assert(count >= 2); 236 237 for (size_t i = 1; i < count; i++) { 238 stream.buffer[i] = cast(char)(stream.get(stream.data)); 239 } 240 241 if (!jansson_d.utf.utf8_check_full(&(stream.buffer[0]), count, null)) { 242 goto out_; 243 } 244 245 stream.buffer[count] = '\0'; 246 } else { 247 stream.buffer[1] = '\0'; 248 } 249 } 250 251 c = stream.buffer[stream.buffer_pos++]; 252 253 stream.position++; 254 255 if (c == '\n') { 256 stream.line++; 257 stream.last_column = stream.column; 258 stream.column = 0; 259 } else if (jansson_d.utf.utf8_check_first(cast(char)(c))) { 260 /* 261 * track the Unicode character column, so increment only if 262 * this is the first character of a UTF-8 sequence 263 */ 264 stream.column++; 265 } 266 267 return c; 268 269 out_: 270 stream.state = .STREAM_STATE_ERROR; 271 .error_set(error, mixin (.stream_to_lex!("stream")), jansson_d.jansson.json_error_code_t.json_error_invalid_utf8, "unable to decode byte 0x%x", c); 272 273 return .STREAM_STATE_ERROR; 274 } 275 276 pure nothrow @trusted @nogc @live 277 private void stream_unget(scope .stream_t* stream, int c) 278 279 in 280 { 281 assert(stream != null); 282 } 283 284 do 285 { 286 if ((c == .STREAM_STATE_EOF) || (c == .STREAM_STATE_ERROR)) { 287 return; 288 } 289 290 stream.position--; 291 292 if (c == '\n') { 293 stream.line--; 294 stream.column = stream.last_column; 295 } else if (jansson_d.utf.utf8_check_first(cast(char)(c))) { 296 stream.column--; 297 } 298 299 assert(stream.buffer_pos > 0); 300 stream.buffer_pos--; 301 assert(stream.buffer[stream.buffer_pos] == c); 302 } 303 304 nothrow @nogc @live 305 private int lex_get(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error) 306 307 in 308 { 309 assert(lex != null); 310 } 311 312 do 313 { 314 return .stream_get(&lex.stream, error); 315 } 316 317 nothrow @trusted @nogc 318 private void lex_save(scope .lex_t* lex, int c) 319 320 in 321 { 322 assert(lex != null); 323 } 324 325 do 326 { 327 jansson_d.strbuffer.strbuffer_append_byte(&lex.saved_text, cast(char)(c)); 328 } 329 330 nothrow @nogc @live 331 private int lex_get_save(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error) 332 333 in 334 { 335 assert(lex != null); 336 } 337 338 do 339 { 340 int c = .stream_get(&lex.stream, error); 341 342 if ((c != .STREAM_STATE_EOF) && (c != .STREAM_STATE_ERROR)) { 343 .lex_save(lex, c); 344 } 345 346 return c; 347 } 348 349 pure nothrow @trusted @nogc @live 350 private void lex_unget(scope .lex_t* lex, int c) 351 352 in 353 { 354 assert(lex != null); 355 } 356 357 do 358 { 359 .stream_unget(&lex.stream, c); 360 } 361 362 pure nothrow @trusted @nogc @live 363 private void lex_unget_unsave(scope .lex_t* lex, int c) 364 365 in 366 { 367 assert(lex != null); 368 } 369 370 do 371 { 372 if ((c != .STREAM_STATE_EOF) && (c != .STREAM_STATE_ERROR)) { 373 /* 374 * Since we treat warnings as errors, when assertions are turned 375 * off the "d" variable would be set but never used. Which is 376 * treated as an error by GCC. 377 */ 378 //#if !defined(NDEBUG) 379 //char d; 380 //#endif 381 382 .stream_unget(&lex.stream, c); 383 384 version (NDEBUG) { 385 jansson_d.strbuffer.strbuffer_pop(&lex.saved_text); 386 } else { 387 char d = jansson_d.strbuffer.strbuffer_pop(&lex.saved_text); 388 } 389 390 //assert(c == d); 391 } 392 } 393 394 nothrow @trusted @nogc 395 private void lex_save_cached(scope .lex_t* lex) 396 397 in 398 { 399 assert(lex != null); 400 } 401 402 do 403 { 404 while (lex.stream.buffer[lex.stream.buffer_pos] != '\0') { 405 .lex_save(lex, lex.stream.buffer[lex.stream.buffer_pos]); 406 lex.stream.buffer_pos++; 407 lex.stream.position++; 408 } 409 } 410 411 nothrow @trusted @nogc 412 private void lex_free_string(scope .lex_t* lex) 413 414 in 415 { 416 assert(lex != null); 417 } 418 419 do 420 { 421 jansson_d.jansson_private.jsonp_free(lex.value.string_.val); 422 lex.value.string_.val = null; 423 lex.value.string_.len = 0; 424 } 425 426 /* assumes that str points to 'u' plus at least 4 valid hex digits */ 427 pure nothrow @trusted @nogc @live 428 private int decode_unicode_escape(scope const char* str) 429 430 in 431 { 432 assert(str != null); 433 assert(str[0] == 'u'); 434 } 435 436 do 437 { 438 int value = 0; 439 440 for (size_t i = 1; i <= 4; i++) { 441 char c = str[i]; 442 value <<= 4; 443 444 if (mixin (.l_isdigit!("c"))) { 445 value += c - '0'; 446 } else if (mixin (.l_islower!("c"))) { 447 value += c - 'a' + 10; 448 } else if (mixin (.l_isupper!("c"))) { 449 value += c - 'A' + 10; 450 } else { 451 return -1; 452 } 453 } 454 455 return value; 456 } 457 458 nothrow @nogc @live 459 private void lex_scan_string(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error) 460 461 in 462 { 463 assert(lex != null); 464 } 465 466 do 467 { 468 char* t = void; 469 const (char)* p = void; 470 471 lex.value.string_.val = null; 472 lex.token = .TOKEN_INVALID; 473 474 int c = .lex_get_save(lex, error); 475 476 while (c != '"') { 477 if (c == .STREAM_STATE_ERROR) { 478 goto out_; 479 } else if (c == .STREAM_STATE_EOF) { 480 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_premature_end_of_input, "premature end of input"); 481 482 goto out_; 483 } else if ((0 <= c) && (c <= 0x1F)) { 484 /* control character */ 485 .lex_unget_unsave(lex, c); 486 487 if (c == '\n') { 488 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "unexpected newline"); 489 } else { 490 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "control character 0x%x", c); 491 } 492 493 goto out_; 494 } else if (c == '\\') { 495 c = .lex_get_save(lex, error); 496 497 if (c == 'u') { 498 c = .lex_get_save(lex, error); 499 500 for (size_t i = 0; i < 4; i++) { 501 if (!mixin (.l_isxdigit!("c"))) { 502 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid escape"); 503 504 goto out_; 505 } 506 507 c = .lex_get_save(lex, error); 508 } 509 } else if ((c == '"') || (c == '\\') || (c == '/') || (c == 'b') || (c == 'f') || (c == 'n') || (c == 'r') || (c == 't')) { 510 c = .lex_get_save(lex, error); 511 } else { 512 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid escape"); 513 514 goto out_; 515 } 516 } else { 517 c = .lex_get_save(lex, error); 518 } 519 } 520 521 /* 522 * the actual value is at most of the same length as the source 523 * string_, because: 524 * - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte 525 * - a single \uXXXX escape (length 6) is converted to at most 3 bytes 526 * - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair 527 * are converted to 4 bytes 528 */ 529 t = cast(char*)(jansson_d.jansson_private.jsonp_malloc(lex.saved_text.length_ + 1)); 530 531 if (t == null) { 532 /* this is not very nice, since TOKEN_INVALID is returned */ 533 goto out_; 534 } 535 536 lex.value.string_.val = t; 537 538 /* + 1 to skip the " */ 539 assert(jansson_d.strbuffer.strbuffer_value(&lex.saved_text) != null); 540 p = jansson_d.strbuffer.strbuffer_value(&lex.saved_text) + 1; 541 542 while (*p != '"') { 543 if (*p == '\\') { 544 p++; 545 546 if (*p == 'u') { 547 int value = .decode_unicode_escape(p); 548 549 if (value < 0) { 550 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1); 551 552 goto out_; 553 } 554 555 p += 5; 556 557 if ((0xD800 <= value) && (value <= 0xDBFF)) { 558 /* surrogate pair */ 559 if ((*p == '\\') && (*(p + 1) == 'u')) { 560 int value2 = .decode_unicode_escape(++p); 561 562 if (value2 < 0) { 563 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1); 564 565 goto out_; 566 } 567 568 p += 5; 569 570 if ((0xDC00 <= value2) && (value2 <= 0xDFFF)) { 571 /* valid second surrogate */ 572 value = ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x010000; 573 } else { 574 /* invalid second surrogate */ 575 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode '\\u%04X\\u%04X'", value, value2); 576 577 goto out_; 578 } 579 } else { 580 /* no second surrogate */ 581 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode '\\u%04X'", value); 582 583 goto out_; 584 } 585 } else if ((0xDC00 <= value) && (value <= 0xDFFF)) { 586 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid Unicode '\\u%04X'", value); 587 588 goto out_; 589 } 590 591 size_t length_ = void; 592 593 if (jansson_d.utf.utf8_encode(value, t, &length_)) { 594 assert(0); 595 } 596 597 t += length_; 598 } else { 599 switch (*p) { 600 case '"': 601 case '\\': 602 case '/': 603 *t = *p; 604 605 break; 606 607 case 'b': 608 *t = '\b'; 609 610 break; 611 612 case 'f': 613 *t = '\f'; 614 615 break; 616 617 case 'n': 618 *t = '\n'; 619 620 break; 621 622 case 'r': 623 *t = '\r'; 624 625 break; 626 627 case 't': 628 *t = '\t'; 629 630 break; 631 632 default: 633 assert(0); 634 } 635 636 t++; 637 p++; 638 } 639 } else { 640 *(t++) = *(p++); 641 } 642 } 643 644 *t = '\0'; 645 lex.value.string_.len = t - lex.value.string_.val; 646 lex.token = .TOKEN_STRING; 647 648 return; 649 650 out_: 651 .lex_free_string(lex); 652 } 653 654 /* disabled if using cmake */ 655 version (JANSSON_USING_CMAKE) { 656 } else { 657 static if (jansson_d.jansson_config.JSON_INTEGER_IS_LONG_LONG) { 658 static if (__traits(compiles, core.stdc.stdlib._strtoi64)) { 659 private alias json_strtoint = core.stdc.stdlib._strtoi64; 660 } else { 661 private alias json_strtoint = core.stdc.stdlib.strtoll; 662 } 663 } else { 664 private alias json_strtoint = core.stdc.stdlib.strtol; 665 } 666 } 667 668 nothrow @nogc @live 669 private int lex_scan_number(scope .lex_t* lex, int c, scope jansson_d.jansson.json_error_t* error) 670 671 in 672 { 673 assert(lex != null); 674 } 675 676 do 677 { 678 lex.token = .TOKEN_INVALID; 679 680 if (c == '-') { 681 c = .lex_get_save(lex, error); 682 } 683 684 if (c == '0') { 685 c = .lex_get_save(lex, error); 686 687 if (mixin (.l_isdigit!("c"))) { 688 .lex_unget_unsave(lex, c); 689 690 return -1; 691 } 692 } else if (mixin (.l_isdigit!("c"))) { 693 do { 694 c = .lex_get_save(lex, error); 695 } while (mixin (.l_isdigit!("c"))); 696 } else { 697 .lex_unget_unsave(lex, c); 698 699 return -1; 700 } 701 702 if ((!(lex.flags & jansson_d.jansson.JSON_DECODE_INT_AS_REAL)) && (c != '.') && (c != 'E') && (c != 'e')) { 703 .lex_unget_unsave(lex, c); 704 705 const char* saved_text = jansson_d.strbuffer.strbuffer_value(&lex.saved_text); 706 707 core.stdc.errno.errno = 0; 708 const (char)* end = null; 709 jansson_d.jansson.json_int_t intval = .json_strtoint(saved_text, &end, 10); 710 711 if (core.stdc.errno.errno == core.stdc.errno.ERANGE) { 712 if (intval < 0) { 713 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_numeric_overflow, "too big negative integer"); 714 } else { 715 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_numeric_overflow, "too big integer"); 716 } 717 718 return -1; 719 } 720 721 assert(end == (saved_text + lex.saved_text.length_)); 722 723 lex.token = .TOKEN_INTEGER; 724 lex.value.integer = intval; 725 726 return 0; 727 } 728 729 if (c == '.') { 730 c = .lex_get(lex, error); 731 732 if (!mixin (.l_isdigit!("c"))) { 733 .lex_unget(lex, c); 734 735 return -1; 736 } 737 738 .lex_save(lex, c); 739 740 do { 741 c = .lex_get_save(lex, error); 742 } while (mixin (.l_isdigit!("c"))); 743 } 744 745 if ((c == 'E') || (c == 'e')) { 746 c = .lex_get_save(lex, error); 747 748 if ((c == '+') || (c == '-')) { 749 c = .lex_get_save(lex, error); 750 } 751 752 if (!mixin (.l_isdigit!("c"))) { 753 .lex_unget_unsave(lex, c); 754 755 return -1; 756 } 757 758 do { 759 c = .lex_get_save(lex, error); 760 } while (mixin (.l_isdigit!("c"))); 761 } 762 763 .lex_unget_unsave(lex, c); 764 765 double doubleval = void; 766 767 if (!jansson_d.jansson_private.jsonp_strtod(&lex.saved_text, &doubleval)) { 768 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_numeric_overflow, "real number overflow"); 769 770 return -1; 771 } 772 773 lex.token = .TOKEN_REAL; 774 lex.value.real_ = doubleval; 775 776 return 0; 777 } 778 779 nothrow @trusted @nogc 780 private int lex_scan(scope .lex_t* lex, scope jansson_d.jansson.json_error_t* error) 781 782 in 783 { 784 assert(lex != null); 785 } 786 787 do 788 { 789 jansson_d.strbuffer.strbuffer_clear(&lex.saved_text); 790 791 if (lex.token == .TOKEN_STRING) { 792 .lex_free_string(lex); 793 } 794 795 int c = void; 796 797 do { 798 c = .lex_get(lex, error); 799 } while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r')); 800 801 if (c == .STREAM_STATE_EOF) { 802 lex.token = .TOKEN_EOF; 803 804 goto out_; 805 } 806 807 if (c == .STREAM_STATE_ERROR) { 808 lex.token = .TOKEN_INVALID; 809 810 goto out_; 811 } 812 813 .lex_save(lex, c); 814 815 if ((c == '{') || (c == '}') || (c == '[') || (c == ']') || (c == ':') || (c == ',')) { 816 lex.token = c; 817 } else if (c == '"') { 818 .lex_scan_string(lex, error); 819 } else if ((mixin (.l_isdigit!("c"))) || (c == '-')) { 820 if (.lex_scan_number(lex, c, error)) { 821 goto out_; 822 } 823 } else if (mixin (.l_isalpha!("c"))) { 824 /* eat up the whole identifier for clearer error messages */ 825 826 do { 827 c = .lex_get_save(lex, error); 828 } while (mixin (.l_isalpha!("c"))); 829 830 .lex_unget_unsave(lex, c); 831 832 const char* saved_text = jansson_d.strbuffer.strbuffer_value(&lex.saved_text); 833 834 if (core.stdc..string.strcmp(saved_text, "true") == 0) { 835 lex.token = .TOKEN_TRUE; 836 } else if (core.stdc..string.strcmp(saved_text, "false") == 0) { 837 lex.token = .TOKEN_FALSE; 838 } else if (core.stdc..string.strcmp(saved_text, "null") == 0) { 839 lex.token = .TOKEN_NULL; 840 } else { 841 lex.token = .TOKEN_INVALID; 842 } 843 } else { 844 /* 845 * save the rest of the input UTF-8 sequence to get an error 846 * message of valid UTF-8 847 */ 848 .lex_save_cached(lex); 849 lex.token = .TOKEN_INVALID; 850 } 851 852 out_: 853 return lex.token; 854 } 855 856 pure nothrow @trusted @nogc @live 857 private char* lex_steal_string(scope .lex_t* lex, scope size_t* out_len) 858 859 in 860 { 861 assert(lex != null); 862 assert(out_len != null); 863 } 864 865 do 866 { 867 char* result = null; 868 869 if (lex.token == .TOKEN_STRING) { 870 result = lex.value.string_.val; 871 *out_len = lex.value.string_.len; 872 lex.value.string_.val = null; 873 lex.value.string_.len = 0; 874 } 875 876 return result; 877 } 878 879 nothrow @trusted @nogc 880 private int lex_init(scope .lex_t* lex, .get_func get, size_t flags, scope void* data) 881 882 in 883 { 884 assert(lex != null); 885 } 886 887 do 888 { 889 .stream_init(&lex.stream, get, data); 890 891 if (jansson_d.strbuffer.strbuffer_init(&lex.saved_text)) { 892 return -1; 893 } 894 895 lex.flags = flags; 896 lex.token = .TOKEN_INVALID; 897 898 return 0; 899 } 900 901 nothrow @trusted @nogc 902 private void lex_close(scope .lex_t* lex) 903 904 in 905 { 906 assert(lex != null); 907 } 908 909 do 910 { 911 if (lex.token == .TOKEN_STRING) { 912 .lex_free_string(lex); 913 } 914 915 jansson_d.strbuffer.strbuffer_close(&lex.saved_text); 916 } 917 918 /* parser */ 919 920 nothrow @trusted @nogc 921 private jansson_d.jansson.json_t* parse_object(scope lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error) 922 923 in 924 { 925 assert(lex != null); 926 } 927 928 do 929 { 930 jansson_d.jansson.json_t* object = jansson_d.value.json_object(); 931 932 if (object == null) { 933 return null; 934 } 935 936 .lex_scan(lex, error); 937 938 if (lex.token == '}') { 939 return object; 940 } 941 942 while (true) { 943 if (lex.token != .TOKEN_STRING) { 944 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "string or '}' expected"); 945 946 goto error_; 947 } 948 949 size_t len = void; 950 char* key = .lex_steal_string(lex, &len); 951 952 if (key == null) { 953 return null; 954 } 955 956 if (core.stdc..string.memchr(key, '\0', len)) { 957 jansson_d.jansson_private.jsonp_free(key); 958 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_null_byte_in_key, "NUL byte in object key not supported"); 959 960 goto error_; 961 } 962 963 if (flags & jansson_d.jansson.JSON_REJECT_DUPLICATES) { 964 if (jansson_d.value.json_object_getn(object, key, len)) { 965 jansson_d.jansson_private.jsonp_free(key); 966 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_duplicate_key, "duplicate object key"); 967 968 goto error_; 969 } 970 } 971 972 .lex_scan(lex, error); 973 974 if (lex.token != ':') { 975 jansson_d.jansson_private.jsonp_free(key); 976 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "':' expected"); 977 978 goto error_; 979 } 980 981 .lex_scan(lex, error); 982 jansson_d.jansson.json_t* value = .parse_value(lex, flags, error); 983 984 if (value == null) { 985 jansson_d.jansson_private.jsonp_free(key); 986 987 goto error_; 988 } 989 990 if (jansson_d.value.json_object_setn_new_nocheck(object, key, len, value)) { 991 jansson_d.jansson_private.jsonp_free(key); 992 993 goto error_; 994 } 995 996 jansson_d.jansson_private.jsonp_free(key); 997 998 .lex_scan(lex, error); 999 1000 if (lex.token != ',') { 1001 break; 1002 } 1003 1004 .lex_scan(lex, error); 1005 } 1006 1007 if (lex.token != '}') { 1008 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "'}' expected"); 1009 1010 goto error_; 1011 } 1012 1013 return object; 1014 1015 error_: 1016 jansson_d.jansson.json_decref(object); 1017 1018 return null; 1019 } 1020 1021 nothrow @trusted @nogc 1022 private jansson_d.jansson.json_t* parse_array(scope .lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error) 1023 1024 in 1025 { 1026 assert(lex != null); 1027 } 1028 1029 do 1030 { 1031 jansson_d.jansson.json_t* array = jansson_d.value.json_array(); 1032 1033 if (array == null) { 1034 return null; 1035 } 1036 1037 .lex_scan(lex, error); 1038 1039 if (lex.token == ']') { 1040 return array; 1041 } 1042 1043 while (lex.token) { 1044 jansson_d.jansson.json_t* elem = .parse_value(lex, flags, error); 1045 1046 if (elem == null) { 1047 goto error_; 1048 } 1049 1050 if (jansson_d.value.json_array_append_new(array, elem)) { 1051 goto error_; 1052 } 1053 1054 .lex_scan(lex, error); 1055 1056 if (lex.token != ',') { 1057 break; 1058 } 1059 1060 .lex_scan(lex, error); 1061 } 1062 1063 if (lex.token != ']') { 1064 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "']' expected"); 1065 1066 goto error_; 1067 } 1068 1069 return array; 1070 1071 error_: 1072 jansson_d.jansson.json_decref(array); 1073 1074 return null; 1075 } 1076 1077 nothrow @trusted @nogc 1078 private jansson_d.jansson.json_t* parse_value(scope .lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error) 1079 1080 in 1081 { 1082 assert(lex != null); 1083 } 1084 1085 do 1086 { 1087 lex.depth++; 1088 1089 if (lex.depth > jansson_d.jansson_config.JSON_PARSER_MAX_DEPTH) { 1090 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_stack_overflow, "maximum parsing depth reached"); 1091 1092 return null; 1093 } 1094 1095 jansson_d.jansson.json_t* json = null; 1096 1097 switch (lex.token) { 1098 case .TOKEN_STRING: 1099 const char* value = lex.value.string_.val; 1100 size_t len = lex.value.string_.len; 1101 1102 if (!(flags & jansson_d.jansson.JSON_ALLOW_NUL)) { 1103 if (core.stdc..string.memchr(value, '\0', len)) { 1104 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_null_character, "\\u0000 is not allowed without JSON_ALLOW_NUL"); 1105 1106 return null; 1107 } 1108 } 1109 1110 json = jansson_d.jansson_private.jsonp_stringn_nocheck_own(value, len); 1111 lex.value.string_.val = null; 1112 lex.value.string_.len = 0; 1113 1114 break; 1115 1116 case .TOKEN_INTEGER: 1117 json = jansson_d.value.json_integer(lex.value.integer); 1118 1119 break; 1120 1121 case .TOKEN_REAL: 1122 json = jansson_d.value.json_real(lex.value.real_); 1123 1124 break; 1125 1126 case .TOKEN_TRUE: 1127 json = jansson_d.value.json_true(); 1128 1129 break; 1130 1131 case .TOKEN_FALSE: 1132 json = jansson_d.value.json_false(); 1133 1134 break; 1135 1136 case .TOKEN_NULL: 1137 json = jansson_d.value.json_null(); 1138 1139 break; 1140 1141 case '{': 1142 json = .parse_object(lex, flags, error); 1143 1144 break; 1145 1146 case '[': 1147 json = .parse_array(lex, flags, error); 1148 1149 break; 1150 1151 case .TOKEN_INVALID: 1152 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "invalid token"); 1153 1154 return null; 1155 1156 default: 1157 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "unexpected token"); 1158 1159 return null; 1160 } 1161 1162 if (json == null) { 1163 return null; 1164 } 1165 1166 lex.depth--; 1167 1168 return json; 1169 } 1170 1171 nothrow @trusted @nogc 1172 private jansson_d.jansson.json_t* parse_json(scope .lex_t* lex, size_t flags, scope jansson_d.jansson.json_error_t* error) 1173 1174 in 1175 { 1176 assert(lex != null); 1177 } 1178 1179 do 1180 { 1181 lex.depth = 0; 1182 1183 .lex_scan(lex, error); 1184 1185 if (!(flags & jansson_d.jansson.JSON_DECODE_ANY)) { 1186 if ((lex.token != '[') && (lex.token != '{')) { 1187 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_invalid_syntax, "'[' or '{' expected"); 1188 1189 return null; 1190 } 1191 } 1192 1193 jansson_d.jansson.json_t* result = .parse_value(lex, flags, error); 1194 1195 if (result == null) { 1196 return null; 1197 } 1198 1199 if (!(flags & jansson_d.jansson.JSON_DISABLE_EOF_CHECK)) { 1200 .lex_scan(lex, error); 1201 1202 if (lex.token != .TOKEN_EOF) { 1203 .error_set(error, lex, jansson_d.jansson.json_error_code_t.json_error_end_of_input_expected, "end of file expected"); 1204 jansson_d.jansson.json_decref(result); 1205 1206 return null; 1207 } 1208 } 1209 1210 if (error != null) { 1211 /* Save the position even though there was no error */ 1212 error.position = cast(int)(lex.stream.position); 1213 } 1214 1215 return result; 1216 } 1217 1218 struct string_data_t 1219 { 1220 const (char)* data; 1221 size_t pos; 1222 } 1223 1224 extern (C) 1225 pure nothrow @trusted @nogc @live 1226 private int string_get(scope void* data) 1227 1228 in 1229 { 1230 assert(data != null); 1231 } 1232 1233 do 1234 { 1235 .string_data_t* stream = cast(.string_data_t*)(data); 1236 char c = stream.data[stream.pos]; 1237 1238 if (c == '\0') { 1239 return core.stdc.stdio.EOF; 1240 } else { 1241 stream.pos++; 1242 1243 return cast(ubyte)(c); 1244 } 1245 } 1246 1247 /// 1248 extern (C) 1249 nothrow @trusted @nogc //ToDo: @nodiscard 1250 public jansson_d.jansson.json_t* json_loads(scope const char* string_, size_t flags, scope jansson_d.jansson.json_error_t* error) 1251 1252 do 1253 { 1254 jansson_d.jansson_private.jsonp_error_init(error, "<string>"); 1255 1256 if (string_ == null) { 1257 .error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments"); 1258 1259 return null; 1260 } 1261 1262 .string_data_t stream_data = 1263 { 1264 data: string_, 1265 pos: 0, 1266 }; 1267 1268 .lex_t lex = void; 1269 1270 if (.lex_init(&lex, &.string_get, flags, cast(void*)(&stream_data))) { 1271 return null; 1272 } 1273 1274 jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error); 1275 1276 .lex_close(&lex); 1277 1278 return result; 1279 } 1280 1281 struct buffer_data_t 1282 { 1283 const (char)* data; 1284 size_t len; 1285 size_t pos; 1286 } 1287 1288 extern (C) 1289 pure nothrow @trusted @nogc @live 1290 private int buffer_get(scope void* data) 1291 1292 in 1293 { 1294 assert(data != null); 1295 } 1296 1297 do 1298 { 1299 .buffer_data_t* stream = cast(.buffer_data_t*)(data); 1300 1301 if (stream.pos >= stream.len) { 1302 return core.stdc.stdio.EOF; 1303 } 1304 1305 char c = stream.data[stream.pos]; 1306 stream.pos++; 1307 1308 return cast(ubyte)(c); 1309 } 1310 1311 /// 1312 extern (C) 1313 nothrow @trusted @nogc //ToDo: @nodiscard 1314 public jansson_d.jansson.json_t* json_loadb(scope const char* buffer, size_t buflen, size_t flags, scope jansson_d.jansson.json_error_t* error) 1315 1316 do 1317 { 1318 jansson_d.jansson_private.jsonp_error_init(error, "<buffer>"); 1319 1320 if (buffer == null) { 1321 .error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments"); 1322 1323 return null; 1324 } 1325 1326 .buffer_data_t stream_data = 1327 { 1328 data: buffer, 1329 pos: 0, 1330 len: buflen, 1331 }; 1332 1333 .lex_t lex = void; 1334 1335 if (.lex_init(&lex, &.buffer_get, flags, cast(void*)(&stream_data))) { 1336 return null; 1337 } 1338 1339 jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error); 1340 1341 .lex_close(&lex); 1342 1343 return result; 1344 } 1345 1346 /// 1347 extern (C) 1348 nothrow @trusted @nogc //ToDo: @nodiscard 1349 public jansson_d.jansson.json_t* json_loadf(core.stdc.stdio.FILE* input, size_t flags, scope jansson_d.jansson.json_error_t* error) 1350 1351 do 1352 { 1353 const (char)* source = void; 1354 1355 if (input == core.stdc.stdio.stdin) { 1356 source = "<stdin>"; 1357 } else { 1358 source = "<stream>"; 1359 } 1360 1361 jansson_d.jansson_private.jsonp_error_init(error, source); 1362 1363 if (input == null) { 1364 .error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments"); 1365 1366 return null; 1367 } 1368 1369 .lex_t lex = void; 1370 1371 if (.lex_init(&lex, cast(.get_func)(&core.stdc.stdio.fgetc), flags, cast(void*)(input))) { 1372 return null; 1373 } 1374 1375 jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error); 1376 1377 .lex_close(&lex); 1378 1379 return result; 1380 } 1381 1382 extern (C) 1383 nothrow @nogc @live 1384 private int fd_get_func(scope int* fd) 1385 1386 in 1387 { 1388 assert(fd != null); 1389 } 1390 1391 do 1392 { 1393 static if (__traits(compiles, core.sys.posix.unistd.read)) { 1394 ubyte c = void; 1395 1396 if (core.sys.posix.unistd.read(*fd, &c, 1) == 1) { 1397 return c; 1398 } 1399 } 1400 1401 return core.stdc.stdio.EOF; 1402 } 1403 1404 /// 1405 extern (C) 1406 nothrow @nogc @live //ToDo: @nodiscard 1407 public jansson_d.jansson.json_t* json_loadfd(int input, size_t flags, scope jansson_d.jansson.json_error_t* error) 1408 1409 do 1410 { 1411 const (char)* source = void; 1412 1413 static if (__traits(compiles, core.sys.posix.unistd.STDIN_FILENO)) { 1414 if (input == core.sys.posix.unistd.STDIN_FILENO) { 1415 source = "<stdin>"; 1416 } else { 1417 source = "<stream>"; 1418 } 1419 } else { 1420 source = "<stream>"; 1421 } 1422 1423 jansson_d.jansson_private.jsonp_error_init(error, source); 1424 1425 if (input < 0) { 1426 .error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments"); 1427 1428 return null; 1429 } 1430 1431 .lex_t lex = void; 1432 1433 if (.lex_init(&lex, cast(.get_func)(&.fd_get_func), flags, &input)) { 1434 return null; 1435 } 1436 1437 jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error); 1438 1439 .lex_close(&lex); 1440 1441 return result; 1442 } 1443 1444 /// 1445 extern (C) 1446 nothrow @nogc //ToDo: @nodiscard 1447 public jansson_d.jansson.json_t* json_load_file(scope const char* path, size_t flags, scope jansson_d.jansson.json_error_t* error) 1448 1449 do 1450 { 1451 jansson_d.jansson_private.jsonp_error_init(error, path); 1452 1453 if (path == null) { 1454 .error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments"); 1455 1456 return null; 1457 } 1458 1459 core.stdc.stdio.FILE* fp = core.stdc.stdio.fopen(path, "rb"); 1460 1461 if (fp == null) { 1462 .error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_cannot_open_file, "unable to open %s: %s", path, core.stdc..string.strerror(core.stdc.errno.errno)); 1463 1464 return null; 1465 } 1466 1467 jansson_d.jansson.json_t* result = .json_loadf(fp, flags, error); 1468 1469 core.stdc.stdio.fclose(fp); 1470 1471 return result; 1472 } 1473 1474 enum MAX_BUF_LEN = 1024; 1475 1476 struct callback_data_t 1477 { 1478 char[.MAX_BUF_LEN] data = '\0'; 1479 size_t len; 1480 size_t pos; 1481 jansson_d.jansson.json_load_callback_t callback; 1482 void* arg; 1483 } 1484 1485 extern (C) 1486 nothrow @nogc 1487 private int callback_get(scope void* data) 1488 1489 in 1490 { 1491 assert(data != null); 1492 assert((cast(.callback_data_t*)(data)).callback != null); 1493 } 1494 1495 do 1496 { 1497 .callback_data_t* stream = cast(.callback_data_t*)(data); 1498 1499 if (stream.pos >= stream.len) { 1500 stream.pos = 0; 1501 stream.len = stream.callback(&(stream.data[0]), stream.data.length, stream.arg); 1502 1503 if ((stream.len == 0) || (stream.len == size_t.max)) { 1504 return core.stdc.stdio.EOF; 1505 } 1506 } 1507 1508 char c = stream.data[stream.pos]; 1509 stream.pos++; 1510 1511 return cast(ubyte)(c); 1512 } 1513 1514 /// 1515 extern (C) 1516 nothrow @nogc //ToDo: @nodiscard 1517 public jansson_d.jansson.json_t* json_load_callback(jansson_d.jansson.json_load_callback_t callback, scope void* arg, size_t flags, scope jansson_d.jansson.json_error_t* error) 1518 1519 do 1520 { 1521 .callback_data_t stream_data = void; 1522 core.stdc..string.memset(&stream_data, 0, stream_data.sizeof); 1523 stream_data.callback = callback; 1524 stream_data.arg = arg; 1525 1526 jansson_d.jansson_private.jsonp_error_init(error, "<callback>"); 1527 1528 if (callback == null) { 1529 .error_set(error, null, jansson_d.jansson.json_error_code_t.json_error_invalid_argument, "wrong arguments"); 1530 1531 return null; 1532 } 1533 1534 .lex_t lex = void; 1535 1536 if (.lex_init(&lex, cast(.get_func)(&.callback_get), flags, &stream_data)) { 1537 return null; 1538 } 1539 1540 jansson_d.jansson.json_t* result = .parse_json(&lex, flags, error); 1541 1542 .lex_close(&lex); 1543 1544 return result; 1545 }