json.cpp revision 9795:372fcb921e99
1/* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25/* 26 * This is not really json in the state it is now. 27 * Some differences: 28 * - Double quotes around the key in an object is not enforced. 29 * i.e you can write: { foo : "bar" } instead of { "foo" : "bar" }. 30 * - Comments are allowed. 31 * - The last element in an object or array can have an ending comma. 32 */ 33 34#include "precompiled.hpp" 35#include "utilities/json.hpp" 36#include "utilities/ostream.hpp" 37#include <math.h> 38 39const char* strchrnul_(const char *s, int c) { 40 const char* tmp = strchr(s, c); 41 return tmp == NULL ? s + strlen(s) : tmp; 42} 43 44JSON::JSON(const char* text, bool silent, outputStream* st) 45: start(text), pos(text), mark(text), 46 level(0), line(1), column(0), silent(silent), _valid(true), _st(st) 47{ 48} 49 50void JSON::parse() { 51 assert(start != NULL, "Need something to parse"); 52 if (start == NULL) { 53 _valid = false; 54 error(INTERNAL_ERROR, "JSON parser was called with a string that was NULL."); 55 } else { 56 _valid = parse_json_value(); 57 } 58} 59 60bool JSON::valid() { 61 return _valid; 62} 63 64bool JSON::parse_json_value() { 65 int c; 66 67 c = skip_to_token(); 68 if (c == -1) { 69 return false; 70 } 71 72 // Must start with object or array 73 if (level == 0) { 74 75 switch (c) { 76 case '{': 77 if (parse_json_object() == false) { 78 return false; 79 } 80 c = skip_to_token(); 81 if (c > 0) { 82 mark_pos(); 83 error(SYNTAX_ERROR, "Only one top level object/array is allowed."); 84 return false; 85 } else if (c < 0) { 86 return false; 87 } 88 return true; 89 90 case '[': 91 if (parse_json_array() == false) { 92 return false; 93 } 94 c = skip_to_token(); 95 if (c > 0) { 96 mark_pos(); 97 error(SYNTAX_ERROR, "Only one top level object/array is allowed."); 98 return false; 99 } else if (c < 0) { 100 return false; 101 } 102 return true; 103 104 case 0: 105 error(SYNTAX_ERROR, "EOS was encountered before any json declarations"); 106 return false; 107 108 default: 109 error(SYNTAX_ERROR, "Json must start with an object or an array."); 110 return false; 111 } 112 } else { // level > 0 113 switch (c) { 114 case '{': 115 return parse_json_object(); 116 117 case '[': 118 return parse_json_array(); 119 120 case '"': 121 return parse_json_string(); 122 123 case '-': case '0': 124 case '1': case '2': case '3': 125 case '4': case '5': case '6': 126 case '7': case '8': case '9': 127 return parse_json_number(); 128 129 case 't': 130 return parse_json_symbol("true", JSON_TRUE); 131 132 case 'f': 133 return parse_json_symbol("false", JSON_FALSE); 134 135 case 'n': 136 return parse_json_symbol("null", JSON_NULL); 137 138 case 0: 139 error(SYNTAX_ERROR, "EOS was encountered when expecting a json value."); 140 return false; 141 142 default: 143 error(SYNTAX_ERROR, "Could not parse as a json value (did you forget to quote your strings?)."); 144 return false; 145 } 146 } 147} 148 149// Should only be called when we actually have the start of an object 150// Otherwise it is an internal error 151bool JSON::parse_json_object() { 152 NOT_PRODUCT(const char* prev_pos); 153 int c; 154 155 mark_pos(); 156 // Check that we are not called in error 157 if (expect_any("{", "object start", INTERNAL_ERROR) <= 0) { 158 return false; 159 } 160 161 if (!callback(JSON_OBJECT_BEGIN, NULL, level++)) { 162 return false; 163 } 164 165 for (;;) { 166 mark_pos(); 167 c = skip_to_token(); 168 if (c == 0) { 169 error(SYNTAX_ERROR, "EOS when expecting an object key or object end"); 170 return false; 171 } else if (c < 0) { 172 return false; 173 } else if (c == '}') { 174 // We got here from either empty object "{}" or ending comma "{a:1,}" 175 next(); 176 break; 177 } 178 179 NOT_PRODUCT(prev_pos = pos); 180 if (parse_json_key() == false) { 181 return false; 182 } 183 assert(pos > prev_pos, "parsing stalled"); 184 185 skip_to_token(); 186 mark_pos(); 187 if (expect_any(":", "object key-value separator") <= 0) { 188 return false; 189 } 190 191 skip_to_token(); 192 mark_pos(); 193 NOT_PRODUCT(prev_pos = pos); 194 if (parse_json_value() == false) { 195 return false; 196 } 197 assert(pos > prev_pos, "parsing stalled"); 198 199 c = skip_to_token(); 200 mark_pos(); 201 if (expect_any(",}", "value separator or object end") <= 0) { 202 return false; 203 } 204 if (c == '}') { 205 break; 206 } 207 } 208 209 assert(c == '}', "array parsing ended without object end token ('}')"); 210 return callback(JSON_OBJECT_END, NULL, --level); 211} 212 213// Should only be called when we actually have the start of an array 214// Otherwise it is an internal error 215bool JSON::parse_json_array() { 216 NOT_PRODUCT(const char* prev_pos); 217 int c; 218 219 mark_pos(); 220 // Check that we are not called in error 221 if (expect_any("[", "array start character", INTERNAL_ERROR) <= 0) { 222 return false; 223 } 224 225 if (!callback(JSON_ARRAY_BEGIN, NULL, level++)) { 226 return false; 227 } 228 229 for (;;) { 230 mark_pos(); 231 c = skip_to_token(); 232 if (c == 0) { 233 error(SYNTAX_ERROR, "EOS when expecting a json value or array end"); 234 return false; 235 } else if (c < 0) { 236 return false; 237 } else if (c == ']') { 238 // We got here from either empty array "[]" or ending comma "[1,]" 239 next(); 240 break; 241 } 242 243 mark_pos(); 244 NOT_PRODUCT(prev_pos = pos); 245 if (parse_json_value() == false) { 246 return false; 247 } 248 assert(pos > prev_pos, "parsing stalled"); 249 250 c = skip_to_token(); 251 mark_pos(); 252 if (expect_any(",]", "value separator or array end") <= 0) { 253 return false; 254 } 255 if (c == ']') { 256 break; 257 } 258 } 259 260 assert(c == ']', "array parsing ended without array end token (']')"); 261 return callback(JSON_ARRAY_END, NULL, --level); 262} 263 264bool JSON::parse_json_string(bool key) { 265 const char* end; 266 JSON_VAL v; 267 268 mark_pos(); 269 if (expect_any("\"", "string start character", INTERNAL_ERROR) <= 0) { 270 return false; 271 } 272 273 end = strchr(pos, '"'); // TODO: escapes 274 if (end == NULL) { 275 error(SYNTAX_ERROR, "String started here never ended. Expected \'\"\' before EOS."); 276 return false; 277 } 278 279 v.str.start = pos; 280 v.str.length = end - pos; 281 skip(end - pos); 282 283 if (expect_any("\"", "string end character", INTERNAL_ERROR) <= 0) { 284 return false; 285 } 286 287 if (key == true) { 288 return callback(JSON_KEY, &v, level); 289 } else { 290 return callback(JSON_STRING, &v, level); 291 } 292} 293 294// TODO: hotspot equivalents? 295static bool is_alpha(u_char c) { 296 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 297} 298static bool is_numeric(u_char c) { 299 return (c >= '0' && c <= '9'); 300} 301static bool is_alnum(u_char c) { 302 return is_alpha(c) || is_numeric(c); 303} 304static bool is_word(u_char c) { 305 return c == '_' || is_alnum(c); 306} 307 308// Allow object keys to be without quotation, 309// but then restrict to ([a-zA-Z0-9_])+ 310bool JSON::parse_json_key() { 311 const char* begin; 312 JSON_VAL v; 313 u_char c; 314 315 mark_pos(); 316 c = peek(); 317 if (c == '"') { 318 return parse_json_string(true); 319 } 320 321 begin = pos; 322 c = peek(); 323 if (c == 0) { 324 error(SYNTAX_ERROR, "Got EOS when expecting an object key."); 325 return false; 326 } else if (is_word(c) == false) { 327 error(SYNTAX_ERROR, "Expected an object key, which can be a double-quoted (\") string or a simple string (only alphanumeric characters and underscore, separated by whitespace) that doesn't need to be quoted."); 328 return false; 329 } 330 331 for (;;) { 332 c = peek(); 333 // Allow the key to be delimited by control characters and the object key-value separator ':' 334 if (c <= ' ' || c == ':') { 335 break; 336 } else if (is_word(c) == false) { 337 error(SYNTAX_ERROR, "Object key need to be quoted, or consist entirely of alphanumeric characters and underscores."); 338 return false; 339 } 340 next(); 341 } 342 343 v.str.start = begin; 344 v.str.length = pos - begin; 345 return callback(JSON_KEY, &v, level); 346} 347 348bool JSON::parse_json_number() { 349 double double_value; 350 int tokens, read; 351 JSON_VAL v; 352 353 mark_pos(); 354 355 // Parsing number - for simplicity ints are limited to 2**53 356 // sscanf as a double and check if part is 0. 357 tokens = sscanf(pos, "%lf%n", &double_value, &read); 358 assert(tokens <= 1, "scanf implementation that counts as a token, parsing json numbers will always fail"); 359 if (tokens == 1) { 360 assert(read > 0, "sanity"); 361 362 if (floor(double_value) == double_value) { 363 // No exponent - treat as an int 364 v.int_value = (int)double_value; 365 if (!callback(JSON_NUMBER_INT, &v, level)) { 366 return false; 367 } 368 } else { 369 v.double_value = double_value; 370 if (!callback(JSON_NUMBER_FLOAT, &v, level)) { 371 return false; 372 } 373 } 374 skip(read); 375 return true; 376 } 377 378 error(SYNTAX_ERROR, "Couldn't parse json number (note that exponents are not supported)."); 379 return false; 380} 381 382bool JSON::parse_json_symbol(const char* name, JSON_TYPE symbol) { 383 if (expect_string(name, "maybe you forgot to quote your strings?") == false) { 384 mark_pos(); 385 return false; 386 } 387 return callback(symbol, NULL, level); 388} 389 390void JSON::mark_pos() { 391 assert((mark == start || *(mark - 1)) != 0, "buffer overrun"); 392 assert(mark <= pos, "mark runahead"); 393 394 u_char c; 395 396 while (mark < pos) { 397 c = *mark; 398 assert(c != 0, "pos buffer overrun?"); 399 if (c != 0) { 400 mark++; 401 column++; 402 } 403 if (c == '\n') { 404 line++; 405 column = 0; 406 } 407 } 408 409 assert(mark <= pos, "mark runahead"); 410} 411 412u_char JSON::next() { 413 assert((pos == start || *(pos - 1)) != 0, "buffer overrun"); 414 415 u_char c = *pos; 416 if (c != 0) { 417 pos++; 418 } 419 return c; 420} 421 422u_char JSON::peek() { 423 return *pos; 424} 425 426// Peek ahead i chars (0 is same as peek()) 427u_char JSON::peek(size_t i) { 428 u_char c; 429 const char* p; 430 431 p = pos; 432 c = *p; 433 while (i > 0 && c != 0) { 434 i--; 435 p++; 436 c = *p; 437 } 438 return c; 439} 440 441/* 442 * Check that one of the expected characters is next in the stream. 443 * If not, it is an error. 444 * Returns 0 if EOS is encountered. 445 * Returns -1 if the next character was not one of the expected. 446 * Otherwise consumes and returns the expected character that was encountered. 447 */ 448int JSON::expect_any(const char* valid_chars, const char* error_msg, JSON_ERROR e) { 449 size_t len; 450 u_char c; 451 452 len = strlen(valid_chars); 453 assert(len > 0, "need non-empty string"); 454 455 c = peek(); 456 if (c == 0) { 457 error(e, "Got EOS when expecting %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars); 458 return 0; 459 } 460 for (size_t i = 0; i < len; i++) { 461 if (c == valid_chars[i]) { 462 return next(); 463 } 464 } 465 error(e, "Expected %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars); 466 return -1; 467} 468 469/* 470 * Check that the expected string is next in the stream. 471 * If not, it is an error. 472 * Consumes the expected characters if they are present. 473 * Returns true if the expected characters were present, otherwise false. 474 */ 475bool JSON::expect_string(const char* expected_string, const char* error_msg, JSON_ERROR e) { 476 u_char c, expected_char; 477 size_t len; 478 479 assert(expected_string != NULL, "need non-null string"); 480 len = strlen(expected_string); 481 assert(len > 0, "need non-empty string"); 482 483 for (size_t i = 0; i < len; i++) { 484 expected_char = expected_string[i]; 485 assert(expected_char > ' ', "not sane for control characters"); 486 if (expected_char <= ' ') { 487 error(INTERNAL_ERROR, "expect got a control char"); 488 } 489 c = pos[i]; 490 if (c == 0) { 491 error(e, "EOS encountered when expecting %s (\"%s\")", error_msg, expected_string); 492 return false; 493 } else if (c != expected_char) { 494 error(e, "Expected \"%s\" (%s)", expected_string, error_msg); 495 return false; 496 } 497 } 498 skip(len); 499 return true; 500} 501 502/* 503 * Skip i characters. 504 * Returns number of characters skipped. 505 */ 506size_t JSON::skip(size_t i) { 507 u_char c; 508 size_t j; 509 510 c = peek(); 511 for (j = i; c != 0 && j > 0; j--) { 512 c = next(); 513 } 514 return i - j; 515} 516 517/* 518 * Skip whitespace and comments. 519 * Returns the first token after whitespace/comments without consuming it 520 * Returns 0 if EOS is encountered. 521 * Returns -1 if there is an error 522 */ 523int JSON::skip_to_token() { 524 for (;;) { 525 int c = peek(0); 526 if (c == '/') { 527 u_char c2 = peek(1); 528 if (c2 == '/') { 529 c = skip_line_comment(); 530 } else if (c2 == '*') { 531 c = skip_block_comment(); 532 if (c < 0) { 533 return -1; 534 } 535 } 536 // Fall through to keep checking if there 537 // are more whitespace / comments to skip 538 } 539 if (c == 0 || c > ' ') { 540 return c; 541 } 542 next(); 543 } 544 return 0; 545} 546 547/* 548 * Skip to, and return the wanted char without consuming it 549 * Returns 0 if EOS is encountered. 550 */ 551u_char JSON::skip_to(u_char want) { 552 // We want the bookkeeping done in next(). 553 // Otherwise strchr could have been used. 554 u_char c; 555 for(;;) { 556 c = peek(); 557 if (c == 0 || c == want) { 558 return c; 559 } 560 next(); 561 } 562} 563 564/* 565 * Should only be called when we actually have a line comment to skip. 566 * Otherwise it is an internal error. 567 * 568 * Will return the first token after the line comment without consuming it. 569 * Returns 0 if EOS is encoutered. 570 */ 571u_char JSON::skip_line_comment() { 572 u_char c; 573 574 // Check that we are not called in error 575 expect_any("/", "line comment start", INTERNAL_ERROR); 576 expect_any("/", "line comment start", INTERNAL_ERROR); 577 578 c = skip_to('\n'); 579 if (c == 0) { 580 return 0; 581 } 582 next(); 583 return next(); 584} 585 586/* 587 * Should only be called when we actually have a block comment to skip. 588 * Otherwise it is an internal error. 589 * 590 * Returns the first token after the block comment without consuming it. 591 * Returns -1 if EOS is encountered in the middle of a comment. 592 */ 593int JSON::skip_block_comment() { 594 const char* current; 595 596 // Check that we are not called in error. 597 if (peek() != '/' || peek(1) != '*') { 598 // Let expect handle EOS. 599 expect_string("/*", "block comment start", INTERNAL_ERROR); 600 return 0; 601 } 602 603 current = pos; 604 for (;;) { 605 current = strchrnul_(current, '*'); 606 607 if (current[0] == 0 || current[1] == 0) { 608 // Advance error marker to start of block comment 609 mark_pos(); 610 error(SYNTAX_ERROR, "Block comment started here never ended. Expected \"*/\" before EOS."); 611 return -1; 612 } 613 614 if (current[1] == '/') { 615 pos = current; 616 if (expect_string("*/", "block comment end", INTERNAL_ERROR) == false) { 617 return -1; 618 } 619 // Found block comment end 620 return peek(); 621 } 622 current++; 623 } 624} 625 626const char* JSON::strerror(JSON_ERROR e) { 627 switch (e) { 628 case SYNTAX_ERROR: 629 return "Syntax error"; 630 case INTERNAL_ERROR: 631 return "Internal error"; 632 case KEY_ERROR: 633 return "Key error"; 634 case VALUE_ERROR: 635 return "Value error"; 636 default: 637 ShouldNotReachHere(); 638 return "Unknown error"; 639 } 640} 641 642void JSON::error(JSON_ERROR e, const char* format, ...) { 643 _valid = false; 644 645 if (!silent) { 646 const char* line_start; 647 const char* tmp; 648 size_t line_length; 649 va_list args; 650 u_char c; 651 652 _st->print("%s on line %u byte %u: ", JSON::strerror(e), line, column + 1); 653 va_start(args, format); 654 _st->vprint(format, args); 655 _st->cr(); 656 va_end(args); 657 658 line_start = mark - column; 659 assert(line_start >= start, "out of bounds"); 660 assert(line_start <= mark, "out of bounds"); 661 assert(line_start == start || line_start[-1] == '\n', "line counting error"); 662 663 c = *pos; 664 if (c == 0) { 665 _st->print(" Got "); 666 _st->print_cr("EOS."); 667 } 668 tmp = mark; 669 c = *tmp; 670 if (c > ' ') { 671 _st->print(" At "); 672 _st->print("'"); 673 while (c > ' ') { 674 _st->print("%c", c); 675 tmp++; 676 c = *tmp; 677 } 678 _st->print_cr("'."); 679 } 680 681 // Skip to newline or EOS 682 tmp = strchrnul_(mark, '\n'); 683 line_length = tmp - line_start; 684 685 _st->print_cr("%s", line_start); 686 } 687} 688 689#ifndef PRODUCT 690void JSONTest::test(const char* text, bool should_pass) { 691 JSONTest json(text); 692 if (should_pass) { 693 assert(json.valid() == true, "failed on a valid json string"); 694 if (VerboseInternalVMTests) { 695 tty->print_cr("-- json test passed as expected --"); 696 } 697 } else { 698 assert(json.valid() == false, "succeeded on an invalid json string"); 699 if (VerboseInternalVMTests) { 700 tty->print_cr("-- json test failed as expected --"); 701 } 702 } 703} 704 705JSONTest::JSONTest(const char* text) : JSON(text, !VerboseInternalVMTests, tty) { 706 prev = JSON_NONE; 707 parse(); 708} 709 710bool JSONTest::test() { 711 JSONTest::test("{}", true); 712 JSONTest::test("[]", true); 713 JSONTest::test(" { } ", true); 714 JSONTest::test(" [ ] ", true); 715 716 JSONTest::test("\"error\"", false); 717 JSONTest::test("error", false); 718 JSONTest::test("1", false); 719 JSONTest::test("1.2", false); 720 JSONTest::test("true", false); 721 JSONTest::test("false", false); 722 JSONTest::test("null", false); 723 724 JSONTest::test("[ 1 ]", true); 725 JSONTest::test("[ 1, ]", true); 726 JSONTest::test("[ true ]", true); 727 JSONTest::test("[ true, ]", true); 728 JSONTest::test("[ false ]", true); 729 JSONTest::test("[ false, ]", true); 730 JSONTest::test("[ null ]", true); 731 JSONTest::test("[ null, ]", true); 732 JSONTest::test("[ \"\" ]", true); 733 JSONTest::test("[ \"\", ]", true); 734 JSONTest::test("[ \"elem1\" ]", true); 735 JSONTest::test("[ \"elem1\", ]", true); 736 JSONTest::test("[ \"elem1\", ]", true); 737 JSONTest::test("[ \"elem1\" ]", true); 738 JSONTest::test("[ \"elem1\", \"elem2\" ]", true); 739 JSONTest::test("[ \"elem1\", \"elem2\", ]", true); 740 741 742 JSONTest::test("[ \"elem1\" ] { }", false); 743 JSONTest::test("[ elem1, \"elem2\" ]", false); 744 JSONTest::test("[ \"elem1\"", false); 745 JSONTest::test("[ \"elem1 ]", false); 746 JSONTest::test("[ \"elem1\", \"elem2\"", false); 747 JSONTest::test("[ truefoo ]", false); 748 JSONTest::test("[ falsefoo ]", false); 749 JSONTest::test("[ nullfoo ]", false); 750 751 JSONTest::test("{ key : 1 }", true); 752 JSONTest::test("{ key : 1, }", true); 753 JSONTest::test("{ key : true }", true); 754 JSONTest::test("{ key : true, }", true); 755 JSONTest::test("{ key : false }", true); 756 JSONTest::test("{ key : false, }", true); 757 JSONTest::test("{ key : null }", true); 758 JSONTest::test("{ key : null, }", true); 759 JSONTest::test("{ \"\" : \"\" }", true); 760 JSONTest::test("{ \"\" : \"\", }", true); 761 JSONTest::test("{ \"key1\" : \"val1\" }", true); 762 JSONTest::test("{ \"key1\" : \"val1\", }", true); 763 JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }", true); 764 JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }", true); 765 766 JSONTest::test("{ \"key\" : \"val\" } [ \"error\" ]", false); 767 JSONTest::test("{ \"key\" : \"val\" ", false); 768 769 JSONTest::test("/**/ { }", true); 770 JSONTest::test("/* */ { }", true); 771 JSONTest::test("/*foo*/ { }", true); 772 JSONTest::test("/* *foo */ { }", true); 773 JSONTest::test("/* *foo* */ { }", true); 774 JSONTest::test("/* /*foo */ { }", true); 775 JSONTest::test("{ } /* foo */", true); 776 JSONTest::test("{ } /* foo */ ", true); 777 JSONTest::test("{ } //", true); 778 JSONTest::test("{ } // ", true); 779 JSONTest::test("{ } // foo", true); 780 781 JSONTest::test("/* * / { }", false); 782 JSONTest::test("/ * */ { }", false); 783 JSONTest::test("// { }", false); 784 JSONTest::test("/* { } */", false); 785 JSONTest::test("/* { } */ ", false); 786 JSONTest::test("/* { } ", false); 787 JSONTest::test("{ } /* ", false); 788 JSONTest::test("/* { } *", false); 789 JSONTest::test("{ /* } */", false); 790 JSONTest::test("[ /* ] */", false); 791 JSONTest::test("{ key : \"val\", /* } */", false); 792 JSONTest::test("[ \"val\", /* ] */", false); 793 794 JSONTest::test("/* comment */{ key1 : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"���\" ], key7 : \"val\",}", true); 795 JSONTest::test("/* comment */ { \"key1\" : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"���\" ], key7 : \"val\",}", true); 796 JSONTest::test("/*comment*/{\"ff1 fsd\":{\"���\":{\"���\":[\"���\",\"���\"]},\"���\":true},\"���\":[\"���\"],\"foo\":\"���\",}", true); 797 JSONTest::test("/* comment */ { key1 error : { \"���\" : { \"���\" : [ \"���\", \"���\" ] }, \"���\" : true }, \"baz\" : [ \"���\" ], foo : \"���\",}", false); // first key needs to be quoted since it contains a space 798 799 800 JSONTest::test("[\n]", true); 801 802 JSONTest::test( 803 "[" "\n" 804 " {" 805 " // pattern to match against class+method+signature" "\n" 806 " // leading and trailing wildcard (*) allowed" "\n" 807 " match: \"foo.bar.*\"," "\n" 808 " " "\n" 809 " // override defaults for specified compiler" "\n" 810 " // we may differentiate between levels too. TBD." "\n" 811 " c1: {" "\n" 812 " //override c1 presets " "\n" 813 " array_bounds_check_removal: false" "\n" 814 " }," "\n" 815 "" "\n" 816 " c2: {" "\n" 817 " // control inlining of method" "\n" 818 " // + force inline, - dont inline" "\n" 819 " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" 820 " }," "\n" 821 "" "\n" 822 " // directives outside a specific preset applies to all compilers" "\n" 823 " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" 824 " print_assembly: true," "\n" 825 " verify_oopmaps: true," "\n" 826 " max_loop_unrolling: 5" "\n" 827 " }," "\n" 828 " {" "\n" 829 " // matching several patterns require an array" "\n" 830 " match: [\"baz.*\",\"frob*\"]," "\n" 831 "" "\n" 832 " // only enable c1 for this directive" "\n" 833 " // all enabled by default. Command disables all not listed" "\n" 834 " enable: \"c1\"," "\n" 835 "" "\n" 836 " // applies to all compilers" "\n" 837 " // + force inline, - dont inline" "\n" 838 " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" 839 " print_inlining: true," "\n" 840 "" "\n" 841 " // force matching compiles to be blocking/syncronous" "\n" 842 " blocking_compile: true" "\n" 843 " }," "\n" 844 "]" "\n", true); 845 846 return true; 847} 848 849void JSONTest::log(uint indent, const char* format, ...) { 850 if (VerboseInternalVMTests) { 851 if (prev != JSON_KEY) { 852 for (uint i = 0; i < indent; i++) { 853 _st->print(" "); 854 } 855 } 856 va_list args; 857 va_start(args, format); 858 _st->vprint(format, args); 859 va_end(args); 860 } 861} 862 863bool JSONTest::callback(JSON_TYPE t, JSON_VAL* v, uint rlevel) { 864 switch (t) { 865 case JSON_OBJECT_BEGIN: 866 log(rlevel, "{\n"); 867 prev = JSON_NONE; // Only care about JSON_KEY, to indent correctly 868 return true; 869 870 case JSON_OBJECT_END: 871 log(rlevel, "},\n"); 872 prev = JSON_NONE; 873 return true; 874 875 case JSON_ARRAY_BEGIN: 876 log(rlevel, "[\n"); 877 prev = JSON_NONE; 878 return true; 879 880 case JSON_ARRAY_END: 881 log(rlevel, "],\n"); 882 prev = JSON_NONE; 883 return true; 884 885 case JSON_KEY: 886 if (VerboseInternalVMTests) { 887 for (uint i = 0; i < rlevel; i++) { 888 _st->print(" "); 889 } 890 _st->print("<key>"); 891 for (size_t i = 0; i < v->str.length; i++) { 892 u_char c = v->str.start[i]; 893 assert(c != 0, "string overrun"); 894 if (c == 0) { 895 return false; 896 } 897 _st->print("%c", c); 898 } 899 _st->print(" : "); 900 } 901 prev = JSON_KEY; 902 return true; 903 904 case JSON_STRING: 905 if (VerboseInternalVMTests) { 906 if (prev != JSON_KEY) { 907 for (uint i = 0; i < rlevel; i++) { 908 _st->print(" "); 909 } 910 } 911 _st->print("<str>"); 912 for (size_t i = 0; i < v->str.length; i++) { 913 u_char c = v->str.start[i]; 914 assert(c != 0, "string overrun"); 915 if (c == 0) { 916 return false; 917 } 918 _st->print("%c", c); 919 } 920 _st->print(",\n"); 921 } 922 prev = JSON_NONE; 923 return true; 924 925 case JSON_NUMBER_INT: 926 log(rlevel, "<int>%" PRId64 ",\n", v->int_value); 927 prev = JSON_NONE; 928 return true; 929 930 case JSON_NUMBER_FLOAT: 931 log(rlevel, "<double>%lf,\n", v->double_value); 932 prev = JSON_NONE; 933 return true; 934 935 case JSON_TRUE: 936 log(rlevel, "<true>,\n"); 937 prev = JSON_NONE; 938 return true; 939 940 case JSON_FALSE: 941 log(rlevel, "<false>,\n"); 942 prev = JSON_NONE; 943 return true; 944 945 case JSON_NULL: 946 log(rlevel, "<null>,\n"); 947 prev = JSON_NONE; 948 return true; 949 950 default: 951 error(INTERNAL_ERROR, "unknown JSON type"); 952 return false; 953 } 954} 955#endif 956