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