1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) Valentin V. Bartenev 5 * Copyright (C) NGINX, Inc. 6 */ 7 8 #include <nxt_main.h> 9 #include <nxt_conf.h> 10 #if 0 11 #include <math.h> 12 #include <float.h> 13 #endif 14 15 16 #define NXT_CONF_MAX_SHORT_STRING 14 17 #define NXT_CONF_MAX_STRING NXT_INT32_T_MAX 18 19 20 typedef enum { 21 NXT_CONF_VALUE_NULL = 0, 22 NXT_CONF_VALUE_BOOLEAN, 23 NXT_CONF_VALUE_INTEGER, 24 NXT_CONF_VALUE_NUMBER, 25 NXT_CONF_VALUE_SHORT_STRING, 26 NXT_CONF_VALUE_STRING, 27 NXT_CONF_VALUE_ARRAY, 28 NXT_CONF_VALUE_OBJECT, 29 } nxt_conf_value_type_t; 30 31 32 typedef enum { 33 NXT_CONF_OP_PASS = 0, 34 NXT_CONF_OP_CREATE, 35 NXT_CONF_OP_REPLACE, 36 NXT_CONF_OP_DELETE, 37 } nxt_conf_op_action_t; 38 39 40 typedef struct nxt_conf_array_s nxt_conf_array_t; 41 typedef struct nxt_conf_object_s nxt_conf_object_t; 42 43 44 struct nxt_conf_value_s { 45 union { 46 uint8_t boolean; /* 1 bit. */ 47 int64_t integer; 48 double number; 49 50 struct { 51 u_char start[NXT_CONF_MAX_SHORT_STRING]; 52 uint8_t length; 53 } str; 54 55 struct { 56 u_char *start; 57 uint32_t length; 58 } nxt_packed string; 59 60 nxt_conf_array_t *array; 61 nxt_conf_object_t *object; 62 } nxt_packed u; 63 64 uint8_t type; /* 3 bits. */ 65 } nxt_aligned(8); 66 67 68 struct nxt_conf_array_s { 69 nxt_uint_t count; 70 nxt_conf_value_t elements[]; 71 }; 72 73 74 typedef struct { 75 nxt_conf_value_t name; 76 nxt_conf_value_t value; 77 } nxt_conf_object_member_t; 78 79 80 struct nxt_conf_object_s { 81 nxt_uint_t count; 82 nxt_conf_object_member_t members[]; 83 }; 84 85 86 struct nxt_conf_op_s { 87 uint32_t index; 88 uint32_t action; /* nxt_conf_op_action_t */ 89 void *ctx; 90 nxt_conf_op_t *next; 91 }; 92 93 94 static u_char *nxt_conf_json_skip_space(u_char *start, u_char *end); 95 static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, 96 u_char *start, u_char *end, nxt_conf_json_error_t *error); 97 static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, 98 u_char *start, u_char *end, nxt_conf_json_error_t *error); 99 static nxt_int_t nxt_conf_object_hash_add(nxt_mp_t *mp, 100 nxt_lvlhsh_t *lvlhsh, nxt_conf_object_member_t *member); 101 static nxt_int_t nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq, 102 void *data); 103 static void *nxt_conf_object_hash_alloc(void *data, size_t size); 104 static void nxt_conf_object_hash_free(void *data, void *p); 105 static u_char *nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, 106 u_char *start, u_char *end, nxt_conf_json_error_t *error); 107 static u_char *nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, 108 u_char *start, u_char *end, nxt_conf_json_error_t *error); 109 static u_char *nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, 110 u_char *start, u_char *end, nxt_conf_json_error_t *error); 111 static void nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos, 112 const char *detail); 113 114 static nxt_int_t nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op, 115 nxt_conf_value_t *dst, nxt_conf_value_t *src); 116 static nxt_int_t nxt_conf_copy_object(nxt_mp_t *mp, nxt_conf_op_t *op, 117 nxt_conf_value_t *dst, nxt_conf_value_t *src); 118 119 static size_t nxt_conf_json_integer_length(nxt_conf_value_t *value); 120 static u_char *nxt_conf_json_print_integer(u_char *p, nxt_conf_value_t *value); 121 static size_t nxt_conf_json_string_length(nxt_conf_value_t *value); 122 static u_char *nxt_conf_json_print_string(u_char *p, nxt_conf_value_t *value); 123 static size_t nxt_conf_json_array_length(nxt_conf_value_t *value, 124 nxt_conf_json_pretty_t *pretty); 125 static u_char *nxt_conf_json_print_array(u_char *p, nxt_conf_value_t *value, 126 nxt_conf_json_pretty_t *pretty); 127 static size_t nxt_conf_json_object_length(nxt_conf_value_t *value, 128 nxt_conf_json_pretty_t *pretty); 129 static u_char *nxt_conf_json_print_object(u_char *p, nxt_conf_value_t *value, 130 nxt_conf_json_pretty_t *pretty); 131 132 static size_t nxt_conf_json_escape_length(u_char *p, size_t size); 133 static u_char *nxt_conf_json_escape(u_char *dst, u_char *src, size_t size); 134 135 136 #define nxt_conf_json_newline(p) \ 137 ((p)[0] = '\r', (p)[1] = '\n', (p) + 2) 138 139 140 nxt_inline u_char * 141 nxt_conf_json_indentation(u_char *p, uint32_t level) 142 { 143 while (level) { 144 *p++ = '\t'; 145 level--; 146 } 147 148 return p; 149 } 150 151 152 void 153 nxt_conf_get_string(nxt_conf_value_t *value, nxt_str_t *str) 154 { 155 if (value->type == NXT_CONF_VALUE_SHORT_STRING) { 156 str->length = value->u.str.length; 157 str->start = value->u.str.start; 158 159 } else { 160 str->length = value->u.string.length; 161 str->start = value->u.string.start; 162 } 163 } 164 165 166 void 167 nxt_conf_set_string(nxt_conf_value_t *value, nxt_str_t *str) 168 { 169 if (str->length > NXT_CONF_MAX_SHORT_STRING) { 170 value->type = NXT_CONF_VALUE_STRING; 171 value->u.string.length = str->length; 172 value->u.string.start = str->start; 173 174 } else { 175 value->type = NXT_CONF_VALUE_SHORT_STRING; 176 value->u.str.length = str->length; 177 178 nxt_memcpy(value->u.str.start, str->start, str->length); 179 } 180 } 181 182 183 nxt_int_t 184 nxt_conf_set_string_dup(nxt_conf_value_t *value, nxt_mp_t *mp, nxt_str_t *str) 185 { 186 nxt_str_t tmp, *ptr; 187 188 if (str->length > NXT_CONF_MAX_SHORT_STRING) { 189 value->type = NXT_CONF_VALUE_STRING; 190 191 ptr = nxt_str_dup(mp, &tmp, str); 192 if (nxt_slow_path(ptr == NULL)) { 193 return NXT_ERROR; 194 } 195 196 value->u.string.length = tmp.length; 197 value->u.string.start = tmp.start; 198 199 } else { 200 value->type = NXT_CONF_VALUE_SHORT_STRING; 201 value->u.str.length = str->length; 202 203 nxt_memcpy(value->u.str.start, str->start, str->length); 204 } 205 206 return NXT_OK; 207 } 208 209 210 int64_t 211 nxt_conf_get_integer(nxt_conf_value_t *value) 212 { 213 return value->u.integer; 214 } 215 216 217 nxt_uint_t 218 nxt_conf_object_members_count(nxt_conf_value_t *value) 219 { 220 return value->u.object->count; 221 } 222 223 224 nxt_conf_value_t * 225 nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count) 226 { 227 size_t size; 228 nxt_conf_value_t *value; 229 230 size = sizeof(nxt_conf_value_t) 231 + sizeof(nxt_conf_object_t) 232 + count * sizeof(nxt_conf_object_member_t); 233 234 value = nxt_mp_get(mp, size); 235 if (nxt_slow_path(value == NULL)) { 236 return NULL; 237 } 238 239 value->u.object = nxt_pointer_to(value, sizeof(nxt_conf_value_t)); 240 value->u.object->count = count; 241 242 value->type = NXT_CONF_VALUE_OBJECT; 243 244 return value; 245 } 246 247 248 void 249 nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, 250 nxt_conf_value_t *value, uint32_t index) 251 { 252 nxt_conf_object_member_t *member; 253 254 member = &object->u.object->members[index]; 255 256 nxt_conf_set_string(&member->name, name); 257 258 member->value = *value; 259 } 260 261 262 void 263 nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, 264 nxt_str_t *value, uint32_t index) 265 { 266 nxt_conf_object_member_t *member; 267 268 member = &object->u.object->members[index]; 269 270 nxt_conf_set_string(&member->name, name); 271 272 nxt_conf_set_string(&member->value, value); 273 } 274 275 276 nxt_int_t 277 nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, 278 nxt_str_t *name, nxt_str_t *value, uint32_t index) 279 { 280 nxt_conf_object_member_t *member; 281 282 member = &object->u.object->members[index]; 283 284 nxt_conf_set_string(&member->name, name); 285 286 return nxt_conf_set_string_dup(&member->value, mp, value); 287 } 288 289 290 void 291 nxt_conf_set_member_integer(nxt_conf_value_t *object, nxt_str_t *name, 292 int64_t value, uint32_t index) 293 { 294 nxt_conf_object_member_t *member; 295 296 member = &object->u.object->members[index]; 297 298 nxt_conf_set_string(&member->name, name); 299 300 member->value.u.integer = value; 301 member->value.type = NXT_CONF_VALUE_INTEGER; 302 } 303 304 305 void 306 nxt_conf_set_member_null(nxt_conf_value_t *object, nxt_str_t *name, 307 uint32_t index) 308 { 309 nxt_conf_object_member_t *member; 310 311 member = &object->u.object->members[index]; 312 313 nxt_conf_set_string(&member->name, name); 314 315 member->value.type = NXT_CONF_VALUE_NULL; 316 } 317 318 319 nxt_conf_value_t * 320 nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count) 321 { 322 size_t size; 323 nxt_conf_value_t *value; 324 325 size = sizeof(nxt_conf_value_t) 326 + sizeof(nxt_conf_array_t) 327 + count * sizeof(nxt_conf_value_t); 328 329 value = nxt_mp_get(mp, size); 330 if (nxt_slow_path(value == NULL)) { 331 return NULL; 332 } 333 334 value->u.array = nxt_pointer_to(value, sizeof(nxt_conf_value_t)); 335 value->u.array->count = count; 336 337 value->type = NXT_CONF_VALUE_ARRAY; 338 339 return value; 340 } 341 342 343 void 344 nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, 345 nxt_conf_value_t *value) 346 { 347 array->u.array->elements[index] = *value; 348 } 349 350 351 nxt_int_t 352 nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp, 353 nxt_uint_t index, nxt_str_t *value) 354 { 355 nxt_conf_value_t *element; 356 357 element = &array->u.array->elements[index]; 358 359 return nxt_conf_set_string_dup(element, mp, value); 360 } 361 362 363 nxt_uint_t 364 nxt_conf_type(nxt_conf_value_t *value) 365 { 366 switch (value->type) { 367 368 case NXT_CONF_VALUE_NULL: 369 return NXT_CONF_NULL; 370 371 case NXT_CONF_VALUE_BOOLEAN: 372 return NXT_CONF_BOOLEAN; 373 374 case NXT_CONF_VALUE_INTEGER: 375 return NXT_CONF_INTEGER; 376 377 case NXT_CONF_VALUE_NUMBER: 378 return NXT_CONF_NUMBER; 379 380 case NXT_CONF_VALUE_SHORT_STRING: 381 case NXT_CONF_VALUE_STRING: 382 return NXT_CONF_STRING; 383 384 case NXT_CONF_VALUE_ARRAY: 385 return NXT_CONF_ARRAY; 386 387 case NXT_CONF_VALUE_OBJECT: 388 return NXT_CONF_OBJECT; 389 } 390 391 nxt_unreachable(); 392 393 return 0; 394 } 395 396 397 typedef struct { 398 u_char *start; 399 u_char *end; 400 nxt_bool_t last; 401 } nxt_conf_path_parse_t; 402 403 404 static void nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, 405 nxt_str_t *token); 406 407 408 nxt_conf_value_t * 409 nxt_conf_get_path(nxt_conf_value_t *value, nxt_str_t *path) 410 { 411 nxt_str_t token; 412 nxt_int_t index; 413 nxt_conf_path_parse_t parse; 414 415 parse.start = path->start; 416 parse.end = path->start + path->length; 417 parse.last = 0; 418 419 do { 420 nxt_conf_path_next_token(&parse, &token); 421 422 if (token.length == 0) { 423 424 if (parse.last) { 425 break; 426 } 427 428 return NULL; 429 } 430 431 switch (value->type) { 432 433 case NXT_CONF_VALUE_OBJECT: 434 value = nxt_conf_get_object_member(value, &token, NULL); 435 break; 436 437 case NXT_CONF_VALUE_ARRAY: 438 index = nxt_int_parse(token.start, token.length); 439 440 if (index < 0 || index > NXT_INT32_T_MAX) { 441 return NULL; 442 } 443 444 value = nxt_conf_get_array_element(value, index); 445 break; 446 447 default: 448 return NULL; 449 } 450 451 if (value == NULL) { 452 return NULL; 453 } 454 455 } while (parse.last == 0); 456 457 return value; 458 } 459 460 461 static void 462 nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, nxt_str_t *token) 463 { 464 u_char *p, *end; 465 466 end = parse->end; 467 p = parse->start + 1; 468 469 token->start = p; 470 471 while (p < end && *p != '/') { 472 p++; 473 } 474 475 parse->start = p; 476 parse->last = (p >= end); 477 478 token->length = p - token->start; 479 } 480 481 482 nxt_conf_value_t * 483 nxt_conf_get_object_member(nxt_conf_value_t *value, nxt_str_t *name, 484 uint32_t *index) 485 { 486 nxt_str_t str; 487 nxt_uint_t n; 488 nxt_conf_object_t *object; 489 nxt_conf_object_member_t *member; 490 491 if (value->type != NXT_CONF_VALUE_OBJECT) { 492 return NULL; 493 } 494 495 object = value->u.object; 496 497 for (n = 0; n < object->count; n++) { 498 member = &object->members[n]; 499 500 nxt_conf_get_string(&member->name, &str); 501 502 if (nxt_strstr_eq(&str, name)) { 503 504 if (index != NULL) { 505 *index = n; 506 } 507 508 return &member->value; 509 } 510 } 511 512 return NULL; 513 } 514 515 516 nxt_int_t 517 nxt_conf_map_object(nxt_mp_t *mp, nxt_conf_value_t *value, nxt_conf_map_t *map, 518 nxt_uint_t n, void *data) 519 { 520 nxt_str_t str, *s; 521 nxt_uint_t i; 522 nxt_conf_value_t *v; 523 524 union { 525 uint8_t ui8; 526 int32_t i32; 527 int64_t i64; 528 nxt_int_t i; 529 ssize_t size; 530 off_t off; 531 nxt_msec_t msec; 532 double dbl; 533 nxt_str_t str; 534 char *cstrz; 535 void *v; 536 } *ptr; 537 538 for (i = 0; i < n; i++) { 539 540 v = nxt_conf_get_object_member(value, &map[i].name, NULL); 541 542 if (v == NULL || v->type == NXT_CONF_VALUE_NULL) { 543 continue; 544 } 545 546 ptr = nxt_pointer_to(data, map[i].offset); 547 548 switch (map[i].type) { 549 550 case NXT_CONF_MAP_INT8: 551 552 if (v->type == NXT_CONF_VALUE_BOOLEAN) { 553 ptr->ui8 = v->u.boolean; 554 } 555 556 break; 557 558 case NXT_CONF_MAP_INT32: 559 case NXT_CONF_MAP_INT64: 560 case NXT_CONF_MAP_INT: 561 case NXT_CONF_MAP_SIZE: 562 case NXT_CONF_MAP_OFF: 563 case NXT_CONF_MAP_MSEC: 564 565 if (v->type != NXT_CONF_VALUE_INTEGER) { 566 break; 567 } 568 569 switch (map[i].type) { 570 571 case NXT_CONF_MAP_INT32: 572 ptr->i32 = v->u.integer; 573 break; 574 575 case NXT_CONF_MAP_INT64: 576 ptr->i64 = v->u.integer; 577 break; 578 579 case NXT_CONF_MAP_INT: 580 ptr->i = v->u.integer; 581 break; 582 583 case NXT_CONF_MAP_SIZE: 584 ptr->size = v->u.integer; 585 break; 586 587 case NXT_CONF_MAP_OFF: 588 ptr->off = v->u.integer; 589 break; 590 591 case NXT_CONF_MAP_MSEC: 592 ptr->msec = v->u.integer * 1000; 593 break; 594 595 default: 596 nxt_unreachable(); 597 } 598 599 break; 600 601 case NXT_CONF_MAP_DOUBLE: 602 603 if (v->type == NXT_CONF_VALUE_NUMBER) { 604 ptr->dbl = v->u.number; 605 606 } else if (v->type == NXT_CONF_VALUE_INTEGER) { 607 ptr->dbl = v->u.integer; 608 609 } 610 611 break; 612 613 case NXT_CONF_MAP_STR: 614 case NXT_CONF_MAP_STR_COPY: 615 case NXT_CONF_MAP_CSTRZ: 616 617 if (v->type != NXT_CONF_VALUE_SHORT_STRING 618 && v->type != NXT_CONF_VALUE_STRING) 619 { 620 break; 621 } 622 623 nxt_conf_get_string(v, &str); 624 625 switch (map[i].type) { 626 627 case NXT_CONF_MAP_STR: 628 ptr->str = str; 629 break; 630 631 case NXT_CONF_MAP_STR_COPY: 632 633 s = nxt_str_dup(mp, &ptr->str, &str); 634 635 if (nxt_slow_path(s == NULL)) { 636 return NXT_ERROR; 637 } 638 639 break; 640 641 case NXT_CONF_MAP_CSTRZ: 642 643 ptr->cstrz = nxt_str_cstrz(mp, &str); 644 645 if (nxt_slow_path(ptr->cstrz == NULL)) { 646 return NXT_ERROR; 647 } 648 649 break; 650 651 default: 652 nxt_unreachable(); 653 } 654 655 break; 656 657 case NXT_CONF_MAP_PTR: 658 659 ptr->v = v; 660 661 break; 662 } 663 } 664 665 return NXT_OK; 666 } 667 668 669 nxt_conf_value_t * 670 nxt_conf_next_object_member(nxt_conf_value_t *value, nxt_str_t *name, 671 uint32_t *next) 672 { 673 uint32_t n; 674 nxt_conf_object_t *object; 675 nxt_conf_object_member_t *member; 676 677 if (value->type != NXT_CONF_VALUE_OBJECT) { 678 return NULL; 679 } 680 681 n = *next; 682 object = value->u.object; 683 684 if (n >= object->count) { 685 return NULL; 686 } 687 688 member = &object->members[n]; 689 *next = n + 1; 690 691 nxt_conf_get_string(&member->name, name); 692 693 return &member->value; 694 } 695 696 697 nxt_conf_value_t * 698 nxt_conf_get_array_element(nxt_conf_value_t *value, uint32_t index) 699 { 700 nxt_conf_array_t *array; 701 702 if (value->type != NXT_CONF_VALUE_ARRAY) { 703 return NULL; 704 } 705 706 array = value->u.array; 707 708 if (index >= array->count) { 709 return NULL; 710 } 711 712 return &array->elements[index]; 713 } 714 715 716 nxt_int_t 717 nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, nxt_conf_value_t *root, 718 nxt_str_t *path, nxt_conf_value_t *value) 719 { 720 nxt_str_t token; 721 nxt_conf_op_t *op, **parent; 722 nxt_conf_path_parse_t parse; 723 nxt_conf_object_member_t *member; 724 725 parse.start = path->start; 726 parse.end = path->start + path->length; 727 parse.last = 0; 728 729 parent = ops; 730 731 for ( ;; ) { 732 op = nxt_mp_zget(mp, sizeof(nxt_conf_op_t)); 733 if (nxt_slow_path(op == NULL)) { 734 return NXT_ERROR; 735 } 736 737 *parent = op; 738 parent = (nxt_conf_op_t **) &op->ctx; 739 740 nxt_conf_path_next_token(&parse, &token); 741 742 root = nxt_conf_get_object_member(root, &token, &op->index); 743 744 if (parse.last) { 745 break; 746 } 747 748 if (root == NULL) { 749 return NXT_DECLINED; 750 } 751 752 op->action = NXT_CONF_OP_PASS; 753 } 754 755 if (value == NULL) { 756 757 if (root == NULL) { 758 return NXT_DECLINED; 759 } 760 761 op->action = NXT_CONF_OP_DELETE; 762 763 return NXT_OK; 764 } 765 766 if (root == NULL) { 767 768 member = nxt_mp_zget(mp, sizeof(nxt_conf_object_member_t)); 769 if (nxt_slow_path(member == NULL)) { 770 return NXT_ERROR; 771 } 772 773 nxt_conf_set_string(&member->name, &token); 774 775 member->value = *value; 776 777 op->action = NXT_CONF_OP_CREATE; 778 op->ctx = member; 779 780 } else { 781 op->action = NXT_CONF_OP_REPLACE; 782 op->ctx = value; 783 } 784 785 return NXT_OK; 786 } 787 788 789 nxt_conf_value_t * 790 nxt_conf_clone(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *value) 791 { 792 nxt_int_t rc; 793 nxt_conf_value_t *copy; 794 795 copy = nxt_mp_get(mp, sizeof(nxt_conf_value_t)); 796 if (nxt_slow_path(copy == NULL)) { 797 return NULL; 798 } 799 800 rc = nxt_conf_copy_value(mp, op, copy, value); 801 802 if (nxt_slow_path(rc != NXT_OK)) { 803 return NULL; 804 } 805 806 return copy; 807 } 808 809 810 static nxt_int_t 811 nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst, 812 nxt_conf_value_t *src) 813 { 814 size_t size; 815 nxt_int_t rc; 816 nxt_uint_t n; 817 818 if (op != NULL && src->type != NXT_CONF_VALUE_OBJECT) { 819 return NXT_ERROR; 820 } 821 822 dst->type = src->type; 823 824 switch (src->type) { 825 826 case NXT_CONF_VALUE_STRING: 827 828 dst->u.string.start = nxt_mp_nget(mp, src->u.string.length); 829 if (nxt_slow_path(dst->u.string.start == NULL)) { 830 return NXT_ERROR; 831 } 832 833 nxt_memcpy(dst->u.string.start, src->u.string.start, 834 src->u.string.length); 835 836 dst->u.string.length = src->u.string.length; 837 838 break; 839 840 case NXT_CONF_VALUE_ARRAY: 841 842 size = sizeof(nxt_conf_array_t) 843 + src->u.array->count * sizeof(nxt_conf_value_t); 844 845 dst->u.array = nxt_mp_get(mp, size); 846 if (nxt_slow_path(dst->u.array == NULL)) { 847 return NXT_ERROR; 848 } 849 850 dst->u.array->count = src->u.array->count; 851 852 for (n = 0; n < src->u.array->count; n++) { 853 rc = nxt_conf_copy_value(mp, NULL, &dst->u.array->elements[n], 854 &src->u.array->elements[n]); 855 856 if (nxt_slow_path(rc != NXT_OK)) { 857 return NXT_ERROR; 858 } 859 } 860 861 break; 862 863 case NXT_CONF_VALUE_OBJECT: 864 return nxt_conf_copy_object(mp, op, dst, src); 865 866 default: 867 dst->u = src->u; 868 } 869 870 return NXT_OK; 871 } 872 873 874 static nxt_int_t 875 nxt_conf_copy_object(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst, 876 nxt_conf_value_t *src) 877 { 878 size_t size; 879 nxt_int_t rc; 880 nxt_uint_t s, d, count, index; 881 nxt_conf_op_t *pass_op; 882 nxt_conf_value_t *value; 883 nxt_conf_object_member_t *member; 884 885 count = src->u.object->count; 886 887 if (op != NULL) { 888 if (op->action == NXT_CONF_OP_CREATE) { 889 count++; 890 891 } else if (op->action == NXT_CONF_OP_DELETE) { 892 count--; 893 } 894 } 895 896 size = sizeof(nxt_conf_object_t) 897 + count * sizeof(nxt_conf_object_member_t); 898 899 dst->u.object = nxt_mp_get(mp, size); 900 if (nxt_slow_path(dst->u.object == NULL)) { 901 return NXT_ERROR; 902 } 903 904 dst->u.object->count = count; 905 906 s = 0; 907 d = 0; 908 909 pass_op = NULL; 910 911 /* 912 * This initialization is needed only to 913 * suppress a warning on GCC 4.8 and older. 914 */ 915 index = 0; 916 917 do { 918 if (pass_op == NULL) { 919 index = (op == NULL || op->action == NXT_CONF_OP_CREATE) 920 ? src->u.object->count 921 : op->index; 922 } 923 924 while (s != index) { 925 rc = nxt_conf_copy_value(mp, NULL, 926 &dst->u.object->members[d].name, 927 &src->u.object->members[s].name); 928 929 if (nxt_slow_path(rc != NXT_OK)) { 930 return NXT_ERROR; 931 } 932 933 rc = nxt_conf_copy_value(mp, pass_op, 934 &dst->u.object->members[d].value, 935 &src->u.object->members[s].value); 936 937 if (nxt_slow_path(rc != NXT_OK)) { 938 return NXT_ERROR; 939 } 940 941 s++; 942 d++; 943 } 944 945 if (pass_op != NULL) { 946 pass_op = NULL; 947 continue; 948 } 949 950 if (op != NULL) { 951 switch (op->action) { 952 case NXT_CONF_OP_PASS: 953 pass_op = op->ctx; 954 index++; 955 break; 956 957 case NXT_CONF_OP_CREATE: 958 member = op->ctx; 959 960 rc = nxt_conf_copy_value(mp, NULL, 961 &dst->u.object->members[d].name, 962 &member->name); 963 964 if (nxt_slow_path(rc != NXT_OK)) { 965 return NXT_ERROR; 966 } 967 968 dst->u.object->members[d].value = member->value; 969 970 d++; 971 break; 972 973 case NXT_CONF_OP_REPLACE: 974 rc = nxt_conf_copy_value(mp, NULL, 975 &dst->u.object->members[d].name, 976 &src->u.object->members[s].name); 977 978 if (nxt_slow_path(rc != NXT_OK)) { 979 return NXT_ERROR; 980 } 981 982 value = op->ctx; 983 984 dst->u.object->members[d].value = *value; 985 986 s++; 987 d++; 988 break; 989 990 case NXT_CONF_OP_DELETE: 991 s++; 992 break; 993 } 994 995 op = op->next; 996 } 997 998 } while (d != count); 999 1000 dst->type = src->type; 1001 1002 return NXT_OK; 1003 } 1004 1005 1006 nxt_conf_value_t * 1007 nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end, 1008 nxt_conf_json_error_t *error) 1009 { 1010 u_char *p; 1011 nxt_conf_value_t *value; 1012 1013 value = nxt_mp_get(mp, sizeof(nxt_conf_value_t)); 1014 if (nxt_slow_path(value == NULL)) { 1015 return NULL; 1016 } 1017 1018 p = nxt_conf_json_skip_space(start, end); 1019 1020 if (nxt_slow_path(p == end)) { 1021 1022 nxt_conf_json_parse_error(error, start, 1023 "An empty JSON payload isn't allowed. It must be either a literal " 1024 "(null, true, or false), a number, a string (in double quotes " 1025 "\"\"), an array (with brackets []), or an object (with braces {})." 1026 ); 1027 1028 return NULL; 1029 } 1030 1031 p = nxt_conf_json_parse_value(mp, value, p, end, error); 1032 1033 if (nxt_slow_path(p == NULL)) { 1034 return NULL; 1035 } 1036 1037 p = nxt_conf_json_skip_space(p, end); 1038 1039 if (nxt_slow_path(p != end)) { 1040 1041 nxt_conf_json_parse_error(error, p, 1042 "Unexpected character after the end of a valid JSON value." 1043 ); 1044 1045 return NULL; 1046 } 1047 1048 return value; 1049 } 1050 1051 1052 static u_char * 1053 nxt_conf_json_skip_space(u_char *start, u_char *end) 1054 { 1055 u_char *p; 1056 1057 for (p = start; nxt_fast_path(p != end); p++) { 1058 1059 switch (*p) { 1060 case ' ': 1061 case '\t': 1062 case '\r': 1063 case '\n': 1064 continue; 1065 } 1066 1067 break; 1068 } 1069 1070 return p; 1071 } 1072 1073 1074 static u_char * 1075 nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, 1076 u_char *end, nxt_conf_json_error_t *error) 1077 { 1078 u_char ch, *p; 1079 1080 ch = *start; 1081 1082 switch (ch) { 1083 case '{': 1084 return nxt_conf_json_parse_object(mp, value, start, end, error); 1085 1086 case '[': 1087 return nxt_conf_json_parse_array(mp, value, start, end, error); 1088 1089 case '"': 1090 return nxt_conf_json_parse_string(mp, value, start, end, error); 1091 1092 case 't': 1093 if (nxt_fast_path(end - start >= 4 1094 && nxt_memcmp(start, "true", 4) == 0)) 1095 { 1096 value->u.boolean = 1; 1097 value->type = NXT_CONF_VALUE_BOOLEAN; 1098 1099 return start + 4; 1100 } 1101 1102 goto error; 1103 1104 case 'f': 1105 if (nxt_fast_path(end - start >= 5 1106 && nxt_memcmp(start, "false", 5) == 0)) 1107 { 1108 value->u.boolean = 0; 1109 value->type = NXT_CONF_VALUE_BOOLEAN; 1110 1111 return start + 5; 1112 } 1113 1114 goto error; 1115 1116 case 'n': 1117 if (nxt_fast_path(end - start >= 4 1118 && nxt_memcmp(start, "null", 4) == 0)) 1119 { 1120 value->type = NXT_CONF_VALUE_NULL; 1121 return start + 4; 1122 } 1123 1124 goto error; 1125 1126 case '-': 1127 if (nxt_fast_path(end - start > 1)) { 1128 ch = start[1]; 1129 break; 1130 } 1131 1132 goto error; 1133 } 1134 1135 if (nxt_fast_path((ch - '0') <= 9)) { 1136 p = nxt_conf_json_parse_number(mp, value, start, end, error); 1137 1138 if (nxt_slow_path(p == NULL)) { 1139 return NULL; 1140 } 1141 1142 if (p == end) { 1143 return end; 1144 } 1145 1146 switch (*p) { 1147 case ' ': 1148 case '\t': 1149 case '\r': 1150 case '\n': 1151 case ',': 1152 case '}': 1153 case ']': 1154 case '{': 1155 case '[': 1156 case '"': 1157 return p; 1158 } 1159 } 1160 1161 error: 1162 1163 nxt_conf_json_parse_error(error, start, 1164 "A valid JSON value is expected here. It must be either a literal " 1165 "(null, true, or false), a number, a string (in double quotes \"\"), " 1166 "an array (with brackets []), or an object (with braces {})." 1167 ); 1168 1169 return NULL; 1170 } 1171 1172 1173 static const nxt_lvlhsh_proto_t nxt_conf_object_hash_proto 1174 nxt_aligned(64) = 1175 { 1176 NXT_LVLHSH_DEFAULT, 1177 nxt_conf_object_hash_test, 1178 nxt_conf_object_hash_alloc, 1179 nxt_conf_object_hash_free, 1180 }; 1181 1182 1183 static u_char * 1184 nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, 1185 u_char *end, nxt_conf_json_error_t *error) 1186 { 1187 u_char *p, *name; 1188 nxt_mp_t *mp_temp; 1189 nxt_int_t rc; 1190 nxt_uint_t count; 1191 nxt_lvlhsh_t hash; 1192 nxt_lvlhsh_each_t lhe; 1193 nxt_conf_object_t *object; 1194 nxt_conf_object_member_t *member, *element; 1195 1196 mp_temp = nxt_mp_create(1024, 128, 256, 32); 1197 if (nxt_slow_path(mp_temp == NULL)) { 1198 return NULL; 1199 } 1200 1201 nxt_lvlhsh_init(&hash); 1202 1203 count = 0; 1204 p = start; 1205 1206 for ( ;; ) { 1207 p = nxt_conf_json_skip_space(p + 1, end); 1208 1209 if (nxt_slow_path(p == end)) { 1210 1211 nxt_conf_json_parse_error(error, p, 1212 "Unexpected end of JSON payload. There's an object without " 1213 "a closing brace (})." 1214 ); 1215 1216 goto error; 1217 } 1218 1219 if (*p != '"') { 1220 if (nxt_fast_path(*p == '}')) { 1221 break; 1222 } 1223 1224 nxt_conf_json_parse_error(error, p, 1225 "A double quote (\") is expected here. There must be a valid " 1226 "JSON object member starts with a name, which is a string " 1227 "enclosed in double quotes." 1228 ); 1229 1230 goto error; 1231 } 1232 1233 name = p; 1234 1235 count++; 1236 1237 member = nxt_mp_get(mp_temp, sizeof(nxt_conf_object_member_t)); 1238 if (nxt_slow_path(member == NULL)) { 1239 goto error; 1240 } 1241 1242 p = nxt_conf_json_parse_string(mp, &member->name, p, end, error); 1243 1244 if (nxt_slow_path(p == NULL)) { 1245 goto error; 1246 } 1247 1248 rc = nxt_conf_object_hash_add(mp_temp, &hash, member); 1249 1250 if (nxt_slow_path(rc != NXT_OK)) { 1251 1252 if (rc == NXT_DECLINED) { 1253 nxt_conf_json_parse_error(error, name, 1254 "Duplicate object member. All JSON object members must " 1255 "have unique names." 1256 ); 1257 } 1258 1259 goto error; 1260 } 1261 1262 p = nxt_conf_json_skip_space(p, end); 1263 1264 if (nxt_slow_path(p == end)) { 1265 1266 nxt_conf_json_parse_error(error, p, 1267 "Unexpected end of JSON payload. There's an object member " 1268 "without a value." 1269 ); 1270 1271 goto error; 1272 } 1273 1274 if (nxt_slow_path(*p != ':')) { 1275 1276 nxt_conf_json_parse_error(error, p, 1277 "A colon (:) is expected here. There must be a colon after " 1278 "a JSON member name." 1279 ); 1280 1281 goto error; 1282 } 1283 1284 p = nxt_conf_json_skip_space(p + 1, end); 1285 1286 if (nxt_slow_path(p == end)) { 1287 1288 nxt_conf_json_parse_error(error, p, 1289 "Unexpected end of JSON payload. There's an object member " 1290 "without a value." 1291 ); 1292 1293 goto error; 1294 } 1295 1296 p = nxt_conf_json_parse_value(mp, &member->value, p, end, error); 1297 1298 if (nxt_slow_path(p == NULL)) { 1299 goto error; 1300 } 1301 1302 p = nxt_conf_json_skip_space(p, end); 1303 1304 if (nxt_slow_path(p == end)) { 1305 1306 nxt_conf_json_parse_error(error, p, 1307 "Unexpected end of JSON payload. There's an object without " 1308 "a closing brace (})." 1309 ); 1310 1311 goto error; 1312 } 1313 1314 if (*p != ',') { 1315 if (nxt_fast_path(*p == '}')) { 1316 break; 1317 } 1318 1319 nxt_conf_json_parse_error(error, p, 1320 "Either a closing brace (}) or a comma (,) is expected here. " 1321 "Each JSON object must be enclosed in braces and its members " 1322 "must be separated by commas." 1323 ); 1324 1325 goto error; 1326 } 1327 } 1328 1329 object = nxt_mp_get(mp, sizeof(nxt_conf_object_t) 1330 + count * sizeof(nxt_conf_object_member_t)); 1331 if (nxt_slow_path(object == NULL)) { 1332 goto error; 1333 } 1334 1335 value->u.object = object; 1336 value->type = NXT_CONF_VALUE_OBJECT; 1337 1338 object->count = count; 1339 member = object->members; 1340 1341 nxt_lvlhsh_each_init(&lhe, &nxt_conf_object_hash_proto); 1342 1343 for ( ;; ) { 1344 element = nxt_lvlhsh_each(&hash, &lhe); 1345 1346 if (element == NULL) { 1347 break; 1348 } 1349 1350 *member++ = *element; 1351 } 1352 1353 nxt_mp_destroy(mp_temp); 1354 1355 return p + 1; 1356 1357 error: 1358 1359 nxt_mp_destroy(mp_temp); 1360 return NULL; 1361 } 1362 1363 1364 static nxt_int_t 1365 nxt_conf_object_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *lvlhsh, 1366 nxt_conf_object_member_t *member) 1367 { 1368 nxt_lvlhsh_query_t lhq; 1369 1370 nxt_conf_get_string(&member->name, &lhq.key); 1371 1372 lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); 1373 lhq.replace = 0; 1374 lhq.value = member; 1375 lhq.proto = &nxt_conf_object_hash_proto; 1376 lhq.pool = mp; 1377 1378 return nxt_lvlhsh_insert(lvlhsh, &lhq); 1379 } 1380 1381 1382 static nxt_int_t 1383 nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data) 1384 { 1385 nxt_str_t str; 1386 nxt_conf_object_member_t *member; 1387 1388 member = data; 1389 1390 nxt_conf_get_string(&member->name, &str); 1391 1392 return nxt_strstr_eq(&lhq->key, &str) ? NXT_OK : NXT_DECLINED; 1393 } 1394 1395 1396 static void * 1397 nxt_conf_object_hash_alloc(void *data, size_t size) 1398 { 1399 return nxt_mp_align(data, size, size); 1400 } 1401 1402 1403 static void 1404 nxt_conf_object_hash_free(void *data, void *p) 1405 { 1406 nxt_mp_free(data, p); 1407 } 1408 1409 1410 static u_char * 1411 nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, 1412 u_char *end, nxt_conf_json_error_t *error) 1413 { 1414 u_char *p; 1415 nxt_mp_t *mp_temp; 1416 nxt_uint_t count; 1417 nxt_list_t *list; 1418 nxt_conf_array_t *array; 1419 nxt_conf_value_t *element; 1420 1421 mp_temp = nxt_mp_create(1024, 128, 256, 32); 1422 if (nxt_slow_path(mp_temp == NULL)) { 1423 return NULL; 1424 } 1425 1426 list = nxt_list_create(mp_temp, 8, sizeof(nxt_conf_value_t)); 1427 if (nxt_slow_path(list == NULL)) { 1428 goto error; 1429 } 1430 1431 count = 0; 1432 p = start; 1433 1434 for ( ;; ) { 1435 p = nxt_conf_json_skip_space(p + 1, end); 1436 1437 if (nxt_slow_path(p == end)) { 1438 1439 nxt_conf_json_parse_error(error, p, 1440 "Unexpected end of JSON payload. There's an array without " 1441 "a closing bracket (])." 1442 ); 1443 1444 goto error; 1445 } 1446 1447 if (*p == ']') { 1448 break; 1449 } 1450 1451 count++; 1452 1453 element = nxt_list_add(list); 1454 if (nxt_slow_path(element == NULL)) { 1455 goto error; 1456 } 1457 1458 p = nxt_conf_json_parse_value(mp, element, p, end, error); 1459 1460 if (nxt_slow_path(p == NULL)) { 1461 goto error; 1462 } 1463 1464 p = nxt_conf_json_skip_space(p, end); 1465 1466 if (nxt_slow_path(p == end)) { 1467 1468 nxt_conf_json_parse_error(error, p, 1469 "Unexpected end of JSON payload. There's an array without " 1470 "a closing bracket (])." 1471 ); 1472 1473 goto error; 1474 } 1475 1476 if (*p != ',') { 1477 if (nxt_fast_path(*p == ']')) { 1478 break; 1479 } 1480 1481 nxt_conf_json_parse_error(error, p, 1482 "Either a closing bracket (]) or a comma (,) is expected " 1483 "here. Each array must be enclosed in brackets and its " 1484 "members must be separated by commas." 1485 ); 1486 1487 goto error; 1488 } 1489 } 1490 1491 array = nxt_mp_get(mp, sizeof(nxt_conf_array_t) 1492 + count * sizeof(nxt_conf_value_t)); 1493 if (nxt_slow_path(array == NULL)) { 1494 goto error; 1495 } 1496 1497 value->u.array = array; 1498 value->type = NXT_CONF_VALUE_ARRAY; 1499 1500 array->count = count; 1501 element = array->elements; 1502 1503 nxt_list_each(value, list) { 1504 *element++ = *value; 1505 } nxt_list_loop; 1506 1507 nxt_mp_destroy(mp_temp); 1508 1509 return p + 1; 1510 1511 error: 1512 1513 nxt_mp_destroy(mp_temp); 1514 return NULL; 1515 } 1516 1517 1518 static u_char * 1519 nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, 1520 u_char *end, nxt_conf_json_error_t *error) 1521 { 1522 u_char *p, ch, *last, *s; 1523 size_t size, surplus; 1524 uint32_t utf, utf_high; 1525 nxt_uint_t i; 1526 enum { 1527 sw_usual = 0, 1528 sw_escape, 1529 sw_encoded1, 1530 sw_encoded2, 1531 sw_encoded3, 1532 sw_encoded4, 1533 } state; 1534 1535 start++; 1536 1537 state = 0; 1538 surplus = 0; 1539 1540 for (p = start; nxt_fast_path(p != end); p++) { 1541 ch = *p; 1542 1543 switch (state) { 1544 1545 case sw_usual: 1546 1547 if (ch == '"') { 1548 break; 1549 } 1550 1551 if (ch == '\\') { 1552 state = sw_escape; 1553 continue; 1554 } 1555 1556 if (nxt_fast_path(ch >= ' ')) { 1557 continue; 1558 } 1559 1560 nxt_conf_json_parse_error(error, p, 1561 "Unexpected character. All control characters in a JSON " 1562 "string must be escaped." 1563 ); 1564 1565 return NULL; 1566 1567 case sw_escape: 1568 1569 switch (ch) { 1570 case '"': 1571 case '\\': 1572 case '/': 1573 case 'n': 1574 case 'r': 1575 case 't': 1576 case 'b': 1577 case 'f': 1578 surplus++; 1579 state = sw_usual; 1580 continue; 1581 1582 case 'u': 1583 /* 1584 * Basic unicode 6 bytes "\uXXXX" in JSON 1585 * and up to 3 bytes in UTF-8. 1586 * 1587 * Surrogate pair: 12 bytes "\uXXXX\uXXXX" in JSON 1588 * and 3 or 4 bytes in UTF-8. 1589 */ 1590 surplus += 3; 1591 state = sw_encoded1; 1592 continue; 1593 } 1594 1595 nxt_conf_json_parse_error(error, p - 1, 1596 "Unexpected backslash. A literal backslash in a JSON string " 1597 "must be escaped with a second backslash (\\\\)." 1598 ); 1599 1600 return NULL; 1601 1602 case sw_encoded1: 1603 case sw_encoded2: 1604 case sw_encoded3: 1605 case sw_encoded4: 1606 1607 if (nxt_fast_path((ch >= '0' && ch <= '9') 1608 || (ch >= 'A' && ch <= 'F') 1609 || (ch >= 'a' && ch <= 'f'))) 1610 { 1611 state = (state == sw_encoded4) ? sw_usual : state + 1; 1612 continue; 1613 } 1614 1615 nxt_conf_json_parse_error(error, p, 1616 "Invalid escape sequence. An escape sequence in a JSON " 1617 "string must start with a backslash, followed by the lowercase " 1618 "letter u, followed by four hexadecimal digits (\\uXXXX)." 1619 ); 1620 1621 return NULL; 1622 } 1623 1624 break; 1625 } 1626 1627 if (nxt_slow_path(p == end)) { 1628 1629 nxt_conf_json_parse_error(error, p, 1630 "Unexpected end of JSON payload. There's a string without " 1631 "a final double quote (\")." 1632 ); 1633 1634 return NULL; 1635 } 1636 1637 /* Points to the ending quote mark. */ 1638 last = p; 1639 1640 size = last - start - surplus; 1641 1642 if (size > NXT_CONF_MAX_SHORT_STRING) { 1643 1644 if (nxt_slow_path(size > NXT_CONF_MAX_STRING)) { 1645 1646 nxt_conf_json_parse_error(error, start, 1647 "The string is too long. Such a long JSON string value " 1648 "is not supported." 1649 ); 1650 1651 return NULL; 1652 } 1653 1654 value->type = NXT_CONF_VALUE_STRING; 1655 1656 value->u.string.start = nxt_mp_nget(mp, size); 1657 if (nxt_slow_path(value->u.string.start == NULL)) { 1658 return NULL; 1659 } 1660 1661 value->u.string.length = size; 1662 1663 s = value->u.string.start; 1664 1665 } else { 1666 value->type = NXT_CONF_VALUE_SHORT_STRING; 1667 value->u.str.length = size; 1668 1669 s = value->u.str.start; 1670 } 1671 1672 if (surplus == 0) { 1673 nxt_memcpy(s, start, size); 1674 return last + 1; 1675 } 1676 1677 p = start; 1678 1679 do { 1680 ch = *p++; 1681 1682 if (ch != '\\') { 1683 *s++ = ch; 1684 continue; 1685 } 1686 1687 ch = *p++; 1688 1689 switch (ch) { 1690 case '"': 1691 case '\\': 1692 case '/': 1693 *s++ = ch; 1694 continue; 1695 1696 case 'n': 1697 *s++ = '\n'; 1698 continue; 1699 1700 case 'r': 1701 *s++ = '\r'; 1702 continue; 1703 1704 case 't': 1705 *s++ = '\t'; 1706 continue; 1707 1708 case 'b': 1709 *s++ = '\b'; 1710 continue; 1711 1712 case 'f': 1713 *s++ = '\f'; 1714 continue; 1715 } 1716 1717 utf = 0; 1718 utf_high = 0; 1719 1720 for ( ;; ) { 1721 for (i = 0; i < 4; i++) { 1722 utf = (utf << 4) | (p[i] >= 'A' ? 10 + ((p[i] & ~0x20) - 'A') 1723 : p[i] - '0'); 1724 } 1725 1726 p += 4; 1727 1728 if (utf_high != 0) { 1729 if (nxt_slow_path(utf < 0xDC00 || utf > 0xDFFF)) { 1730 1731 nxt_conf_json_parse_error(error, p - 12, 1732 "Invalid JSON encoding sequence. This 12-byte " 1733 "sequence composes an illegal UTF-16 surrogate pair." 1734 ); 1735 1736 return NULL; 1737 } 1738 1739 utf = ((utf_high - 0xD800) << 10) + (utf - 0xDC00) + 0x10000; 1740 1741 break; 1742 } 1743 1744 if (utf < 0xD800 || utf > 0xDFFF) { 1745 break; 1746 } 1747 1748 if (utf > 0xDBFF || p[0] != '\\' || p[1] != 'u') { 1749 1750 nxt_conf_json_parse_error(error, p - 6, 1751 "Invalid JSON encoding sequence. This 6-byte sequence " 1752 "does not represent a valid UTF character." 1753 ); 1754 1755 return NULL; 1756 } 1757 1758 p += 2; 1759 1760 utf_high = utf; 1761 utf = 0; 1762 } 1763 1764 s = nxt_utf8_encode(s, utf); 1765 1766 } while (p != last); 1767 1768 if (size > NXT_CONF_MAX_SHORT_STRING) { 1769 value->u.string.length = s - value->u.string.start; 1770 1771 } else { 1772 value->u.str.length = s - value->u.str.start; 1773 } 1774 1775 return last + 1; 1776 } 1777 1778 1779 static u_char * 1780 nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, 1781 u_char *end, nxt_conf_json_error_t *error) 1782 { 1783 u_char *p, ch; 1784 uint64_t integer; 1785 nxt_int_t sign; 1786 #if 0 1787 uint64_t frac, power 1788 nxt_int_t e, negative; 1789 #endif 1790 1791 static const uint64_t cutoff = NXT_INT64_T_MAX / 10; 1792 static const uint64_t cutlim = NXT_INT64_T_MAX % 10; 1793 1794 ch = *start; 1795 1796 if (ch == '-') { 1797 sign = -1; 1798 start++; 1799 1800 } else { 1801 sign = 1; 1802 } 1803 1804 integer = 0; 1805 1806 for (p = start; nxt_fast_path(p != end); p++) { 1807 ch = *p; 1808 1809 /* Values below '0' become >= 208. */ 1810 ch = ch - '0'; 1811 1812 if (ch > 9) { 1813 break; 1814 } 1815 1816 if (nxt_slow_path(integer >= cutoff 1817 && (integer > cutoff || ch > cutlim))) 1818 { 1819 nxt_conf_json_parse_error(error, start, 1820 "The integer is too large. Such a large JSON integer value " 1821 "is not supported." 1822 ); 1823 1824 return NULL; 1825 } 1826 1827 integer = integer * 10 + ch; 1828 } 1829 1830 if (nxt_slow_path(p - start > 1 && *start == '0')) { 1831 1832 nxt_conf_json_parse_error(error, start, 1833 "The number is invalid. Leading zeros are not allowed in JSON " 1834 "numbers." 1835 ); 1836 1837 return NULL; 1838 } 1839 1840 if (ch != '.') { 1841 value->type = NXT_CONF_VALUE_INTEGER; 1842 value->u.integer = sign * integer; 1843 return p; 1844 } 1845 1846 #if 0 1847 start = p + 1; 1848 1849 frac = 0; 1850 power = 1; 1851 1852 for (p = start; nxt_fast_path(p != end); p++) { 1853 ch = *p; 1854 1855 /* Values below '0' become >= 208. */ 1856 ch = ch - '0'; 1857 1858 if (ch > 9) { 1859 break; 1860 } 1861 1862 if (nxt_slow_path((frac >= cutoff && (frac > cutoff || ch > cutlim)) 1863 || power > cutoff)) 1864 { 1865 return NULL; 1866 } 1867 1868 frac = frac * 10 + ch; 1869 power *= 10; 1870 } 1871 1872 if (nxt_slow_path(p == start)) { 1873 return NULL; 1874 } 1875 1876 value->type = NXT_CONF_VALUE_NUMBER; 1877 value->u.number = integer + (double) frac / power; 1878 1879 value->u.number = copysign(value->u.number, sign); 1880 1881 if (ch == 'e' || ch == 'E') { 1882 start = p + 1; 1883 1884 ch = *start; 1885 1886 if (ch == '-' || ch == '+') { 1887 start++; 1888 } 1889 1890 negative = (ch == '-') ? 1 : 0; 1891 e = 0; 1892 1893 for (p = start; nxt_fast_path(p != end); p++) { 1894 ch = *p; 1895 1896 /* Values below '0' become >= 208. */ 1897 ch = ch - '0'; 1898 1899 if (ch > 9) { 1900 break; 1901 } 1902 1903 e = e * 10 + ch; 1904 1905 if (nxt_slow_path(e > DBL_MAX_10_EXP)) { 1906 return NULL; 1907 } 1908 } 1909 1910 if (nxt_slow_path(p == start)) { 1911 return NULL; 1912 } 1913 1914 if (negative) { 1915 value->u.number /= exp10(e); 1916 1917 } else { 1918 value->u.number *= exp10(e); 1919 } 1920 } 1921 1922 if (nxt_fast_path(isfinite(value->u.number))) { 1923 return p; 1924 } 1925 #else 1926 1927 nxt_conf_json_parse_error(error, start, 1928 "The number is not an integer. JSON numbers with decimals and " 1929 "exponents are not supported." 1930 ); 1931 1932 #endif 1933 1934 return NULL; 1935 } 1936 1937 1938 static void 1939 nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos, 1940 const char *detail) 1941 { 1942 if (error == NULL) { 1943 return; 1944 } 1945 1946 error->pos = pos; 1947 error->detail = (u_char *) detail; 1948 } 1949 1950 1951 size_t 1952 nxt_conf_json_length(nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty) 1953 { 1954 switch (value->type) { 1955 1956 case NXT_CONF_VALUE_NULL: 1957 return nxt_length("null"); 1958 1959 case NXT_CONF_VALUE_BOOLEAN: 1960 return value->u.boolean ? nxt_length("true") : nxt_length("false"); 1961 1962 case NXT_CONF_VALUE_INTEGER: 1963 return nxt_conf_json_integer_length(value); 1964 1965 case NXT_CONF_VALUE_NUMBER: 1966 /* TODO */ 1967 return 0; 1968 1969 case NXT_CONF_VALUE_SHORT_STRING: 1970 case NXT_CONF_VALUE_STRING: 1971 return nxt_conf_json_string_length(value); 1972 1973 case NXT_CONF_VALUE_ARRAY: 1974 return nxt_conf_json_array_length(value, pretty); 1975 1976 case NXT_CONF_VALUE_OBJECT: 1977 return nxt_conf_json_object_length(value, pretty); 1978 } 1979 1980 nxt_unreachable(); 1981 1982 return 0; 1983 } 1984 1985 1986 u_char * 1987 nxt_conf_json_print(u_char *p, nxt_conf_value_t *value, 1988 nxt_conf_json_pretty_t *pretty) 1989 { 1990 switch (value->type) { 1991 1992 case NXT_CONF_VALUE_NULL: 1993 return nxt_cpymem(p, "null", 4); 1994 1995 case NXT_CONF_VALUE_BOOLEAN: 1996 return value->u.boolean ? nxt_cpymem(p, "true", 4) 1997 : nxt_cpymem(p, "false", 5); 1998 1999 case NXT_CONF_VALUE_INTEGER: 2000 return nxt_conf_json_print_integer(p, value); 2001 2002 case NXT_CONF_VALUE_NUMBER: 2003 /* TODO */ 2004 return p; 2005 2006 case NXT_CONF_VALUE_SHORT_STRING: 2007 case NXT_CONF_VALUE_STRING: 2008 return nxt_conf_json_print_string(p, value); 2009 2010 case NXT_CONF_VALUE_ARRAY: 2011 return nxt_conf_json_print_array(p, value, pretty); 2012 2013 case NXT_CONF_VALUE_OBJECT: 2014 return nxt_conf_json_print_object(p, value, pretty); 2015 } 2016 2017 nxt_unreachable(); 2018 2019 return p; 2020 } 2021 2022 2023 static size_t 2024 nxt_conf_json_integer_length(nxt_conf_value_t *value) 2025 { 2026 int64_t num; 2027 2028 num = llabs(value->u.integer); 2029 2030 if (num <= 9999) { 2031 return nxt_length("-9999"); 2032 } 2033 2034 if (num <= 99999999999LL) { 2035 return nxt_length("-99999999999"); 2036 } 2037 2038 return NXT_INT64_T_LEN; 2039 } 2040 2041 2042 static u_char * 2043 nxt_conf_json_print_integer(u_char *p, nxt_conf_value_t *value) 2044 { 2045 return nxt_sprintf(p, p + NXT_INT64_T_LEN, "%L", value->u.integer); 2046 } 2047 2048 2049 static size_t 2050 nxt_conf_json_string_length(nxt_conf_value_t *value) 2051 { 2052 nxt_str_t str; 2053 2054 nxt_conf_get_string(value, &str); 2055 2056 return 2 + nxt_conf_json_escape_length(str.start, str.length); 2057 } 2058 2059 2060 static u_char * 2061 nxt_conf_json_print_string(u_char *p, nxt_conf_value_t *value) 2062 { 2063 nxt_str_t str; 2064 2065 nxt_conf_get_string(value, &str); 2066 2067 *p++ = '"'; 2068 2069 p = nxt_conf_json_escape(p, str.start, str.length); 2070 2071 *p++ = '"'; 2072 2073 return p; 2074 } 2075 2076 2077 static size_t 2078 nxt_conf_json_array_length(nxt_conf_value_t *value, 2079 nxt_conf_json_pretty_t *pretty) 2080 { 2081 size_t len; 2082 nxt_uint_t n; 2083 nxt_conf_array_t *array; 2084 2085 array = value->u.array; 2086 2087 /* [] */ 2088 len = 2; 2089 2090 if (pretty != NULL) { 2091 pretty->level++; 2092 } 2093 2094 value = array->elements; 2095 2096 for (n = 0; n < array->count; n++) { 2097 len += nxt_conf_json_length(&value[n], pretty); 2098 2099 if (pretty != NULL) { 2100 /* Indentation and new line. */ 2101 len += pretty->level + 2; 2102 } 2103 } 2104 2105 if (pretty != NULL) { 2106 pretty->level--; 2107 2108 if (n != 0) { 2109 /* Indentation and new line. */ 2110 len += pretty->level + 2; 2111 } 2112 } 2113 2114 /* Reserve space for "n" commas. */ 2115 return len + n; 2116 } 2117 2118 2119 static u_char * 2120 nxt_conf_json_print_array(u_char *p, nxt_conf_value_t *value, 2121 nxt_conf_json_pretty_t *pretty) 2122 { 2123 nxt_uint_t n; 2124 nxt_conf_array_t *array; 2125 2126 array = value->u.array; 2127 2128 *p++ = '['; 2129 2130 if (array->count != 0) { 2131 value = array->elements; 2132 2133 if (pretty != NULL) { 2134 p = nxt_conf_json_newline(p); 2135 2136 pretty->level++; 2137 p = nxt_conf_json_indentation(p, pretty->level); 2138 } 2139 2140 p = nxt_conf_json_print(p, &value[0], pretty); 2141 2142 for (n = 1; n < array->count; n++) { 2143 *p++ = ','; 2144 2145 if (pretty != NULL) { 2146 p = nxt_conf_json_newline(p); 2147 p = nxt_conf_json_indentation(p, pretty->level); 2148 2149 pretty->more_space = 0; 2150 } 2151 2152 p = nxt_conf_json_print(p, &value[n], pretty); 2153 } 2154 2155 if (pretty != NULL) { 2156 p = nxt_conf_json_newline(p); 2157 2158 pretty->level--; 2159 p = nxt_conf_json_indentation(p, pretty->level); 2160 2161 pretty->more_space = 1; 2162 } 2163 } 2164 2165 *p++ = ']'; 2166 2167 return p; 2168 } 2169 2170 2171 static size_t 2172 nxt_conf_json_object_length(nxt_conf_value_t *value, 2173 nxt_conf_json_pretty_t *pretty) 2174 { 2175 size_t len; 2176 nxt_uint_t n; 2177 nxt_conf_object_t *object; 2178 nxt_conf_object_member_t *member; 2179 2180 object = value->u.object; 2181 2182 /* {} */ 2183 len = 2; 2184 2185 if (pretty != NULL) { 2186 pretty->level++; 2187 } 2188 2189 member = object->members; 2190 2191 for (n = 0; n < object->count; n++) { 2192 len += nxt_conf_json_string_length(&member[n].name) + 1 2193 + nxt_conf_json_length(&member[n].value, pretty) + 1; 2194 2195 if (pretty != NULL) { 2196 /* 2197 * Indentation, space after ":", new line, and possible 2198 * additional empty line between non-empty objects. 2199 */ 2200 len += pretty->level + 1 + 2 + 2; 2201 } 2202 } 2203 2204 if (pretty != NULL) { 2205 pretty->level--; 2206 2207 /* Indentation and new line. */ 2208 len += pretty->level + 2; 2209 } 2210 2211 return len; 2212 } 2213 2214 2215 static u_char * 2216 nxt_conf_json_print_object(u_char *p, nxt_conf_value_t *value, 2217 nxt_conf_json_pretty_t *pretty) 2218 { 2219 nxt_uint_t n; 2220 nxt_conf_object_t *object; 2221 nxt_conf_object_member_t *member; 2222 2223 object = value->u.object; 2224 2225 *p++ = '{'; 2226 2227 if (object->count != 0) { 2228 2229 if (pretty != NULL) { 2230 p = nxt_conf_json_newline(p); 2231 pretty->level++; 2232 } 2233 2234 member = object->members; 2235 2236 n = 0; 2237 2238 for ( ;; ) { 2239 if (pretty != NULL) { 2240 p = nxt_conf_json_indentation(p, pretty->level); 2241 } 2242 2243 p = nxt_conf_json_print_string(p, &member[n].name); 2244 2245 *p++ = ':'; 2246 2247 if (pretty != NULL) { 2248 *p++ = ' '; 2249 } 2250 2251 p = nxt_conf_json_print(p, &member[n].value, pretty); 2252 2253 n++; 2254 2255 if (n == object->count) { 2256 break; 2257 } 2258 2259 *p++ = ','; 2260 2261 if (pretty != NULL) { 2262 p = nxt_conf_json_newline(p); 2263 2264 if (pretty->more_space) { 2265 pretty->more_space = 0; 2266 p = nxt_conf_json_newline(p); 2267 } 2268 } 2269 } 2270 2271 if (pretty != NULL) { 2272 p = nxt_conf_json_newline(p); 2273 2274 pretty->level--; 2275 p = nxt_conf_json_indentation(p, pretty->level); 2276 2277 pretty->more_space = 1; 2278 } 2279 } 2280 2281 *p++ = '}'; 2282 2283 return p; 2284 } 2285 2286 2287 static size_t 2288 nxt_conf_json_escape_length(u_char *p, size_t size) 2289 { 2290 u_char ch; 2291 size_t len; 2292 2293 len = size; 2294 2295 while (size) { 2296 ch = *p++; 2297 2298 if (ch == '\\' || ch == '"') { 2299 len++; 2300 2301 } else if (ch <= 0x1F) { 2302 2303 switch (ch) { 2304 case '\n': 2305 case '\r': 2306 case '\t': 2307 case '\b': 2308 case '\f': 2309 len++; 2310 break; 2311 2312 default: 2313 len += sizeof("\\u001F") - 2; 2314 } 2315 } 2316 2317 size--; 2318 } 2319 2320 return len; 2321 } 2322 2323 2324 static u_char * 2325 nxt_conf_json_escape(u_char *dst, u_char *src, size_t size) 2326 { 2327 u_char ch; 2328 2329 while (size) { 2330 ch = *src++; 2331 2332 if (ch > 0x1F) { 2333 2334 if (ch == '\\' || ch == '"') { 2335 *dst++ = '\\'; 2336 } 2337 2338 *dst++ = ch; 2339 2340 } else { 2341 *dst++ = '\\'; 2342 2343 switch (ch) { 2344 case '\n': 2345 *dst++ = 'n'; 2346 break; 2347 2348 case '\r': 2349 *dst++ = 'r'; 2350 break; 2351 2352 case '\t': 2353 *dst++ = 't'; 2354 break; 2355 2356 case '\b': 2357 *dst++ = 'b'; 2358 break; 2359 2360 case '\f': 2361 *dst++ = 'f'; 2362 break; 2363 2364 default: 2365 *dst++ = 'u'; *dst++ = '0'; *dst++ = '0'; 2366 *dst++ = '0' + (ch >> 4); 2367 2368 ch &= 0xF; 2369 2370 *dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10); 2371 } 2372 } 2373 2374 size--; 2375 } 2376 2377 return dst; 2378 } 2379 2380 2381 void 2382 nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line, 2383 nxt_uint_t *column) 2384 { 2385 u_char *p; 2386 ssize_t symbols; 2387 nxt_uint_t lines; 2388 2389 lines = 1; 2390 2391 for (p = start; p != pos; p++) { 2392 2393 if (*p != '\n') { 2394 continue; 2395 } 2396 2397 lines++; 2398 start = p + 1; 2399 } 2400 2401 symbols = nxt_utf8_length(start, p - start); 2402 2403 if (symbols != -1) { 2404 *line = lines; 2405 *column = 1 + symbols; 2406 } 2407 } 2408