diff options
author | Valentin Bartenev <vbart@nginx.com> | 2017-06-28 18:56:33 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2017-06-28 18:56:33 +0300 |
commit | 53074c3b2905061d3a7cf32f20d7dc481efc488a (patch) | |
tree | e4ec40ac813a0f2c73d33a213ce54e76239ae437 /src/nxt_conf_json.c | |
parent | ec5e540fd7e4c87026c4c94674a7ee758c357d75 (diff) | |
download | unit-53074c3b2905061d3a7cf32f20d7dc481efc488a.tar.gz unit-53074c3b2905061d3a7cf32f20d7dc481efc488a.tar.bz2 |
Configuration: reduced names of structures, functions, and macros.
Diffstat (limited to 'src/nxt_conf_json.c')
-rw-r--r-- | src/nxt_conf_json.c | 1888 |
1 files changed, 0 insertions, 1888 deletions
diff --git a/src/nxt_conf_json.c b/src/nxt_conf_json.c deleted file mode 100644 index 45682245..00000000 --- a/src/nxt_conf_json.c +++ /dev/null @@ -1,1888 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) Valentin V. Bartenev - * Copyright (C) NGINX, Inc. - */ - -#include <nxt_main.h> -#include <nxt_conf.h> -#if 0 -#include <math.h> -#include <float.h> -#endif - - -#define NXT_CONF_JSON_STR_SIZE 14 - - -typedef enum { - NXT_CONF_JSON_NULL = 0, - NXT_CONF_JSON_BOOLEAN, - NXT_CONF_JSON_INTEGER, - NXT_CONF_JSON_NUMBER, - NXT_CONF_JSON_SHORT_STRING, - NXT_CONF_JSON_STRING, - NXT_CONF_JSON_ARRAY, - NXT_CONF_JSON_OBJECT, -} nxt_conf_json_type_t; - - -typedef enum { - NXT_CONF_JSON_OP_PASS = 0, - NXT_CONF_JSON_OP_CREATE, - NXT_CONF_JSON_OP_REPLACE, - NXT_CONF_JSON_OP_DELETE, -} nxt_conf_json_op_action_t; - - -typedef struct nxt_conf_json_array_s nxt_conf_json_array_t; -typedef struct nxt_conf_json_object_s nxt_conf_json_object_t; - - -struct nxt_conf_json_value_s { - union { - uint32_t boolean; /* 1 bit. */ - int64_t integer; - double number; - u_char str[1 + NXT_CONF_JSON_STR_SIZE]; - nxt_str_t *string; - nxt_conf_json_array_t *array; - nxt_conf_json_object_t *object; - } u; - - nxt_conf_json_type_t type:8; /* 3 bits. */ -}; - - -struct nxt_conf_json_array_s { - nxt_uint_t count; - nxt_conf_json_value_t elements[]; -}; - - -typedef struct { - nxt_conf_json_value_t name; - nxt_conf_json_value_t value; -} nxt_conf_json_obj_member_t; - - -struct nxt_conf_json_object_s { - nxt_uint_t count; - nxt_conf_json_obj_member_t members[]; -}; - - -struct nxt_conf_json_op_s { - uint32_t index; - uint32_t action; /* nxt_conf_json_op_action_t */ - void *ctx; - nxt_conf_json_op_t *next; -}; - - -static u_char *nxt_conf_json_skip_space(u_char *start, u_char *end); -static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, - nxt_conf_json_value_t *value, u_char *start, u_char *end); -static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, - nxt_conf_json_value_t *value, u_char *start, u_char *end); -static nxt_int_t nxt_conf_json_object_hash_add(nxt_mp_t *mp, - nxt_lvlhsh_t *lvlhsh, nxt_conf_json_obj_member_t *member); -static nxt_int_t nxt_conf_json_object_hash_test(nxt_lvlhsh_query_t *lhq, - void *data); -static void *nxt_conf_json_object_hash_alloc(void *data, size_t size); -static void nxt_conf_json_object_hash_free(void *data, void *p); -static u_char *nxt_conf_json_parse_array(nxt_mp_t *mp, - nxt_conf_json_value_t *value, u_char *start, u_char *end); -static u_char *nxt_conf_json_parse_string(nxt_mp_t *mp, - nxt_conf_json_value_t *value, u_char *start, u_char *end); -static u_char *nxt_conf_json_parse_number(nxt_mp_t *mp, - nxt_conf_json_value_t *value, u_char *start, u_char *end); - -static nxt_int_t nxt_conf_json_copy_value(nxt_mp_t *mp, nxt_conf_json_op_t *op, - nxt_conf_json_value_t *dst, nxt_conf_json_value_t *src); -static nxt_int_t nxt_conf_json_copy_object(nxt_mp_t *mp, nxt_conf_json_op_t *op, - nxt_conf_json_value_t *dst, nxt_conf_json_value_t *src); - -static size_t nxt_conf_json_integer_length(nxt_conf_json_value_t *value); -static u_char *nxt_conf_json_integer_print(u_char *p, - nxt_conf_json_value_t *value); -static size_t nxt_conf_json_string_length(nxt_conf_json_value_t *value); -static u_char *nxt_conf_json_string_print(u_char *p, - nxt_conf_json_value_t *value); -static size_t nxt_conf_json_array_length(nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty); -static u_char *nxt_conf_json_array_print(u_char *p, - nxt_conf_json_value_t *value, nxt_conf_json_pretty_t *pretty); -static size_t nxt_conf_json_object_length(nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty); -static u_char *nxt_conf_json_object_print(u_char *p, - nxt_conf_json_value_t *value, nxt_conf_json_pretty_t *pretty); - -static size_t nxt_conf_json_escape_length(u_char *p, size_t size); -static u_char *nxt_conf_json_escape(u_char *dst, u_char *src, size_t size); - - -#define nxt_conf_json_newline(p) \ - ((p)[0] = '\r', (p)[1] = '\n', (p) + 2) - - -nxt_inline u_char * -nxt_conf_json_indentation(u_char *p, uint32_t level) -{ - while (level) { - *p++ = '\t'; - level--; - } - - return p; -} - - -nxt_inline void -nxt_conf_json_value_get_string(nxt_conf_json_value_t *value, nxt_str_t *str) -{ - if (value->type == NXT_CONF_JSON_SHORT_STRING) { - str->length = value->u.str[0]; - str->start = &value->u.str[1]; - - } else { - *str = *value->u.string; - } -} - - -typedef struct { - u_char *start; - u_char *end; - nxt_bool_t last; -} nxt_conf_path_parse_t; - - -static void nxt_conf_json_path_next_token(nxt_conf_path_parse_t *parse, - nxt_str_t *token); - - -nxt_conf_json_value_t * -nxt_conf_json_get_value(nxt_conf_json_value_t *value, nxt_str_t *path) -{ - nxt_str_t token; - nxt_conf_path_parse_t parse; - - parse.start = path->start; - parse.end = path->start + path->length; - parse.last = 0; - - do { - nxt_conf_json_path_next_token(&parse, &token); - - if (token.length == 0) { - - if (parse.last) { - break; - } - - return NULL; - } - - value = nxt_conf_json_object_get_member(value, &token, NULL); - - if (value == NULL) { - return NULL; - } - - } while (parse.last == 0); - - return value; -} - - -static void -nxt_conf_json_path_next_token(nxt_conf_path_parse_t *parse, nxt_str_t *token) -{ - u_char *p, *end; - - end = parse->end; - p = parse->start + 1; - - token->start = p; - - while (p < end && *p != '/') { - p++; - } - - parse->start = p; - parse->last = (p >= end); - - token->length = p - token->start; -} - - -nxt_conf_json_value_t * -nxt_conf_json_object_get_member(nxt_conf_json_value_t *value, nxt_str_t *name, - uint32_t *index) -{ - nxt_str_t str; - nxt_uint_t n; - nxt_conf_json_object_t *object; - nxt_conf_json_obj_member_t *member; - - if (value->type != NXT_CONF_JSON_OBJECT) { - return NULL; - } - - object = value->u.object; - - for (n = 0; n < object->count; n++) { - member = &object->members[n]; - - nxt_conf_json_value_get_string(&member->name, &str); - - if (nxt_strstr_eq(&str, name)) { - - if (index != NULL) { - *index = n; - } - - return &member->value; - } - } - - return NULL; -} - - -nxt_int_t -nxt_conf_json_object_map(nxt_conf_json_value_t *value, - nxt_conf_json_object_map_t *map, void *data) -{ - nxt_uint_t i; - nxt_conf_json_value_t *v; - - union { - uint8_t ui8; - int32_t i32; - int64_t i64; - nxt_int_t i; - ssize_t size; - off_t off; - double dbl; - nxt_str_t str; - void *v; - } *ptr; - - for (i = 0; map[i].name.length != 0; i++) { - - v = nxt_conf_json_object_get_member(value, &map[i].name, NULL); - - if (v == NULL || v->type == NXT_CONF_JSON_NULL) { - continue; - } - - ptr = nxt_pointer_to(data, map[i].offset); - - switch (map[i].type) { - - case NXT_CONF_JSON_MAP_INT8: - - if (v->type != NXT_CONF_JSON_BOOLEAN) { - return NXT_ERROR; - } - - ptr->ui8 = v->u.boolean; - - break; - - case NXT_CONF_JSON_MAP_INT32: - case NXT_CONF_JSON_MAP_INT64: - case NXT_CONF_JSON_MAP_INT: - case NXT_CONF_JSON_MAP_SIZE: - case NXT_CONF_JSON_MAP_OFF: - - if (v->type != NXT_CONF_JSON_INTEGER) { - return NXT_ERROR; - } - - switch (map[i].type) { - - case NXT_CONF_JSON_MAP_INT32: - ptr->ui8 = v->u.integer; - break; - - case NXT_CONF_JSON_MAP_INT64: - ptr->i64 = v->u.integer; - break; - - case NXT_CONF_JSON_MAP_INT: - ptr->i = v->u.integer; - break; - - case NXT_CONF_JSON_MAP_SIZE: - ptr->size = v->u.integer; - break; - - case NXT_CONF_JSON_MAP_OFF: - ptr->off = v->u.integer; - break; - - default: - nxt_unreachable(); - } - - break; - - case NXT_CONF_JSON_MAP_DOUBLE: - - if (v->type == NXT_CONF_JSON_NUMBER) { - ptr->dbl = v->u.number; - - } else if (v->type == NXT_CONF_JSON_INTEGER) { - ptr->dbl = v->u.integer; - - } else { - return NXT_ERROR; - } - - break; - - case NXT_CONF_JSON_MAP_STR: - - if (v->type != NXT_CONF_JSON_SHORT_STRING - && v->type != NXT_CONF_JSON_STRING) - { - return NXT_ERROR; - } - - nxt_conf_json_value_get_string(v, &ptr->str); - - break; - - - case NXT_CONF_JSON_MAP_PTR: - - ptr->v = v; - - break; - } - } - - return NXT_OK; -} - - -nxt_conf_json_value_t * -nxt_conf_json_object_next_member(nxt_conf_json_value_t *value, nxt_str_t *name, - uint32_t *next) -{ - uint32_t n; - nxt_conf_json_object_t *object; - nxt_conf_json_obj_member_t *member; - - if (value->type != NXT_CONF_JSON_OBJECT) { - return NULL; - } - - n = *next; - object = value->u.object; - - if (n >= object->count) { - return NULL; - } - - member = &object->members[n]; - *next = n + 1; - - nxt_conf_json_value_get_string(&member->name, name); - - return &member->value; -} - - -nxt_int_t -nxt_conf_json_op_compile(nxt_mp_t *mp, nxt_conf_json_op_t **ops, - nxt_conf_json_value_t *root, nxt_str_t *path, - nxt_conf_json_value_t *value) -{ - nxt_str_t token; - nxt_conf_json_op_t *op, **parent; - nxt_conf_path_parse_t parse; - nxt_conf_json_obj_member_t *member; - - parse.start = path->start; - parse.end = path->start + path->length; - parse.last = 0; - - parent = ops; - - for ( ;; ) { - op = nxt_mp_zget(mp, sizeof(nxt_conf_json_op_t)); - if (nxt_slow_path(op == NULL)) { - return NXT_ERROR; - } - - *parent = op; - parent = (nxt_conf_json_op_t **) &op->ctx; - - nxt_conf_json_path_next_token(&parse, &token); - - root = nxt_conf_json_object_get_member(root, &token, &op->index); - - if (parse.last) { - break; - } - - if (root == NULL) { - return NXT_DECLINED; - } - - op->action = NXT_CONF_JSON_OP_PASS; - } - - if (value == NULL) { - - if (root == NULL) { - return NXT_DECLINED; - } - - op->action = NXT_CONF_JSON_OP_DELETE; - - return NXT_OK; - } - - if (root == NULL) { - - member = nxt_mp_zget(mp, sizeof(nxt_conf_json_obj_member_t)); - if (nxt_slow_path(member == NULL)) { - return NXT_ERROR; - } - - if (token.length > NXT_CONF_JSON_STR_SIZE) { - - member->name.u.string = nxt_mp_get(mp, sizeof(nxt_str_t)); - if (nxt_slow_path(member->name.u.string == NULL)) { - return NXT_ERROR; - } - - *member->name.u.string = token; - member->name.type = NXT_CONF_JSON_STRING; - - } else { - member->name.u.str[0] = token.length; - nxt_memcpy(&member->name.u.str[1], token.start, token.length); - - member->name.type = NXT_CONF_JSON_SHORT_STRING; - } - - member->value = *value; - - op->action = NXT_CONF_JSON_OP_CREATE; - op->ctx = member; - - } else { - op->action = NXT_CONF_JSON_OP_REPLACE; - op->ctx = value; - } - - return NXT_OK; -} - - -nxt_conf_json_value_t * -nxt_conf_json_clone_value(nxt_mp_t *mp, nxt_conf_json_op_t *op, - nxt_conf_json_value_t *value) -{ - nxt_int_t rc; - nxt_conf_json_value_t *copy; - - copy = nxt_mp_get(mp, sizeof(nxt_conf_json_value_t)); - if (nxt_slow_path(copy == NULL)) { - return NULL; - } - - rc = nxt_conf_json_copy_value(mp, op, copy, value); - - if (nxt_slow_path(rc != NXT_OK)) { - return NULL; - } - - return copy; -} - - -static nxt_int_t -nxt_conf_json_copy_value(nxt_mp_t *mp, nxt_conf_json_op_t *op, - nxt_conf_json_value_t *dst, nxt_conf_json_value_t *src) -{ - size_t size; - nxt_int_t rc; - nxt_uint_t n; - - if (op != NULL && src->type != NXT_CONF_JSON_OBJECT) { - return NXT_ERROR; - } - - dst->type = src->type; - - switch (src->type) { - - case NXT_CONF_JSON_STRING: - - dst->u.string = nxt_str_dup(mp, NULL, src->u.string); - - if (nxt_slow_path(dst->u.string == NULL)) { - return NXT_ERROR; - } - - break; - - case NXT_CONF_JSON_ARRAY: - - size = sizeof(nxt_conf_json_array_t) - + src->u.array->count * sizeof(nxt_conf_json_value_t); - - dst->u.array = nxt_mp_get(mp, size); - if (nxt_slow_path(dst->u.array == NULL)) { - return NXT_ERROR; - } - - dst->u.array->count = src->u.array->count; - - for (n = 0; n < src->u.array->count; n++) { - rc = nxt_conf_json_copy_value(mp, NULL, - &dst->u.array->elements[n], - &src->u.array->elements[n]); - - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } - } - - break; - - case NXT_CONF_JSON_OBJECT: - return nxt_conf_json_copy_object(mp, op, dst, src); - - default: - dst->u = src->u; - } - - return NXT_OK; -} - - -static nxt_int_t -nxt_conf_json_copy_object(nxt_mp_t *mp, nxt_conf_json_op_t *op, - nxt_conf_json_value_t *dst, nxt_conf_json_value_t *src) -{ - size_t size; - nxt_int_t rc; - nxt_uint_t s, d, count, index; - nxt_conf_json_op_t *pass_op; - nxt_conf_json_value_t *value; - nxt_conf_json_obj_member_t *member; - - count = src->u.object->count; - - if (op != NULL) { - if (op->action == NXT_CONF_JSON_OP_CREATE) { - count++; - - } else if (op->action == NXT_CONF_JSON_OP_DELETE) { - count--; - } - } - - size = sizeof(nxt_conf_json_object_t) - + count * sizeof(nxt_conf_json_obj_member_t); - - dst->u.object = nxt_mp_get(mp, size); - if (nxt_slow_path(dst->u.object == NULL)) { - return NXT_ERROR; - } - - dst->u.object->count = count; - - s = 0; - d = 0; - - pass_op = NULL; - - /* - * This initialization is needed only to - * suppress a warning on GCC 4.8 and older. - */ - index = 0; - - do { - if (pass_op == NULL) { - index = (op == NULL || op->action == NXT_CONF_JSON_OP_CREATE) - ? src->u.object->count : op->index; - } - - while (s != index) { - rc = nxt_conf_json_copy_value(mp, NULL, - &dst->u.object->members[d].name, - &src->u.object->members[s].name); - - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } - - rc = nxt_conf_json_copy_value(mp, pass_op, - &dst->u.object->members[d].value, - &src->u.object->members[s].value); - - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } - - s++; - d++; - } - - if (pass_op != NULL) { - pass_op = NULL; - continue; - } - - if (op != NULL) { - switch (op->action) { - case NXT_CONF_JSON_OP_PASS: - pass_op = op->ctx; - index++; - break; - - case NXT_CONF_JSON_OP_CREATE: - member = op->ctx; - - rc = nxt_conf_json_copy_value(mp, NULL, - &dst->u.object->members[d].name, - &member->name); - - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } - - dst->u.object->members[d].value = member->value; - - d++; - break; - - case NXT_CONF_JSON_OP_REPLACE: - rc = nxt_conf_json_copy_value(mp, NULL, - &dst->u.object->members[d].name, - &src->u.object->members[s].name); - - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } - - value = op->ctx; - - dst->u.object->members[d].value = *value; - - s++; - d++; - break; - - case NXT_CONF_JSON_OP_DELETE: - s++; - break; - } - - op = op->next; - } - - } while (d != count); - - dst->type = src->type; - - return NXT_OK; -} - - -nxt_conf_json_value_t * -nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end) -{ - u_char *p; - nxt_conf_json_value_t *value; - - value = nxt_mp_get(mp, sizeof(nxt_conf_json_value_t)); - if (nxt_slow_path(value == NULL)) { - return NULL; - } - - p = nxt_conf_json_skip_space(start, end); - - if (nxt_slow_path(p == end)) { - return NULL; - } - - p = nxt_conf_json_parse_value(mp, value, p, end); - - if (nxt_slow_path(p == NULL)) { - return NULL; - } - - p = nxt_conf_json_skip_space(p, end); - - if (nxt_slow_path(p != end)) { - return NULL; - } - - return value; -} - - -static u_char * -nxt_conf_json_skip_space(u_char *start, u_char *end) -{ - u_char *p; - - for (p = start; nxt_fast_path(p != end); p++) { - - switch (*p) { - case ' ': - case '\t': - case '\r': - case '\n': - continue; - } - - break; - } - - return p; -} - - -static u_char * -nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_json_value_t *value, - u_char *start, u_char *end) -{ - u_char ch; - - ch = *start; - - switch (ch) { - case '{': - return nxt_conf_json_parse_object(mp, value, start, end); - - case '[': - return nxt_conf_json_parse_array(mp, value, start, end); - - case '"': - return nxt_conf_json_parse_string(mp, value, start, end); - - case 't': - if (nxt_fast_path(end - start >= 4 - && nxt_memcmp(start, "true", 4) == 0)) - { - value->u.boolean = 1; - value->type = NXT_CONF_JSON_BOOLEAN; - - return start + 4; - } - - return NULL; - - case 'f': - if (nxt_fast_path(end - start >= 5 - && nxt_memcmp(start, "false", 5) == 0)) - { - value->u.boolean = 0; - value->type = NXT_CONF_JSON_BOOLEAN; - - return start + 5; - } - - return NULL; - - case 'n': - if (nxt_fast_path(end - start >= 4 - && nxt_memcmp(start, "null", 4) == 0)) - { - value->type = NXT_CONF_JSON_NULL; - return start + 4; - } - - return NULL; - } - - if (nxt_fast_path(ch == '-' || (ch - '0') <= 9)) { - return nxt_conf_json_parse_number(mp, value, start, end); - } - - return NULL; -} - - -static const nxt_lvlhsh_proto_t nxt_conf_json_object_hash_proto - nxt_aligned(64) = -{ - NXT_LVLHSH_DEFAULT, - nxt_conf_json_object_hash_test, - nxt_conf_json_object_hash_alloc, - nxt_conf_json_object_hash_free, -}; - - -static u_char * -nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_json_value_t *value, - u_char *start, u_char *end) -{ - u_char *p; - nxt_mp_t *mp_temp; - nxt_int_t rc; - nxt_uint_t count; - nxt_lvlhsh_t hash; - nxt_lvlhsh_each_t lhe; - nxt_conf_json_object_t *object; - nxt_conf_json_obj_member_t *member, *element; - - p = nxt_conf_json_skip_space(start + 1, end); - - if (nxt_slow_path(p == end)) { - return NULL; - } - - mp_temp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp_temp == NULL)) { - return NULL; - } - - nxt_lvlhsh_init(&hash); - - count = 0; - - if (*p != '}') { - - for ( ;; ) { - count++; - - if (*p != '"') { - goto error; - } - - member = nxt_mp_get(mp_temp, sizeof(nxt_conf_json_obj_member_t)); - if (nxt_slow_path(member == NULL)) { - goto error; - } - - p = nxt_conf_json_parse_string(mp, &member->name, p, end); - - if (nxt_slow_path(p == NULL)) { - goto error; - } - - rc = nxt_conf_json_object_hash_add(mp_temp, &hash, member); - - if (nxt_slow_path(rc != NXT_OK)) { - goto error; - } - - p = nxt_conf_json_skip_space(p, end); - - if (nxt_slow_path(p == end || *p != ':')) { - goto error; - } - - p = nxt_conf_json_skip_space(p + 1, end); - - if (nxt_slow_path(p == end)) { - goto error; - } - - p = nxt_conf_json_parse_value(mp, &member->value, p, end); - - if (nxt_slow_path(p == NULL)) { - goto error; - } - - p = nxt_conf_json_skip_space(p, end); - - if (nxt_slow_path(p == end)) { - goto error; - } - - if (*p == '}') { - break; - } - - if (nxt_slow_path(*p != ',')) { - goto error; - } - - p = nxt_conf_json_skip_space(p + 1, end); - - if (nxt_slow_path(p == end)) { - goto error; - } - } - } - - object = nxt_mp_get(mp, sizeof(nxt_conf_json_object_t) - + count * sizeof(nxt_conf_json_obj_member_t)); - if (nxt_slow_path(object == NULL)) { - goto error; - } - - value->u.object = object; - value->type = NXT_CONF_JSON_OBJECT; - - object->count = count; - member = object->members; - - nxt_memzero(&lhe, sizeof(nxt_lvlhsh_each_t)); - lhe.proto = &nxt_conf_json_object_hash_proto; - - for ( ;; ) { - element = nxt_lvlhsh_each(&hash, &lhe); - - if (element == NULL) { - break; - } - - *member++ = *element; - } - - nxt_mp_destroy(mp_temp); - - return p + 1; - -error: - - nxt_mp_destroy(mp_temp); - return NULL; -} - - -static nxt_int_t -nxt_conf_json_object_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *lvlhsh, - nxt_conf_json_obj_member_t *member) -{ - nxt_lvlhsh_query_t lhq; - - nxt_conf_json_value_get_string(&member->name, &lhq.key); - - lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); - lhq.replace = 0; - lhq.value = member; - lhq.proto = &nxt_conf_json_object_hash_proto; - lhq.pool = mp; - - return nxt_lvlhsh_insert(lvlhsh, &lhq); -} - - -static nxt_int_t -nxt_conf_json_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_str_t str; - nxt_conf_json_obj_member_t *member; - - member = data; - - nxt_conf_json_value_get_string(&member->name, &str); - - if (nxt_strstr_eq(&lhq->key, &str)) { - return NXT_OK; - } - - return NXT_DECLINED; -} - - -static void * -nxt_conf_json_object_hash_alloc(void *data, size_t size) -{ - return nxt_mp_align(data, size, size); -} - - -static void -nxt_conf_json_object_hash_free(void *data, void *p) -{ - nxt_mp_free(data, p); -} - - -static u_char * -nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_json_value_t *value, - u_char *start, u_char *end) -{ - u_char *p; - nxt_mp_t *mp_temp; - nxt_uint_t count; - nxt_list_t *list; - nxt_conf_json_array_t *array; - nxt_conf_json_value_t *element; - - p = nxt_conf_json_skip_space(start + 1, end); - - if (nxt_slow_path(p == end)) { - return NULL; - } - - mp_temp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp_temp == NULL)) { - return NULL; - } - - list = nxt_list_create(mp_temp, 8, sizeof(nxt_conf_json_value_t)); - if (nxt_slow_path(list == NULL)) { - goto error; - } - - count = 0; - - if (*p != ']') { - - for ( ;; ) { - count++; - - element = nxt_list_add(list); - if (nxt_slow_path(element == NULL)) { - goto error; - } - - p = nxt_conf_json_parse_value(mp, element, p, end); - - if (nxt_slow_path(p == NULL)) { - goto error; - } - - p = nxt_conf_json_skip_space(p, end); - - if (nxt_slow_path(p == end)) { - goto error; - } - - if (*p == ']') { - break; - } - - if (nxt_slow_path(*p != ',')) { - goto error; - } - - p = nxt_conf_json_skip_space(p + 1, end); - - if (nxt_slow_path(p == end)) { - goto error; - } - } - } - - array = nxt_mp_get(mp, sizeof(nxt_conf_json_array_t) - + count * sizeof(nxt_conf_json_value_t)); - if (nxt_slow_path(array == NULL)) { - goto error; - } - - value->u.array = array; - value->type = NXT_CONF_JSON_ARRAY; - - array->count = count; - element = array->elements; - - nxt_list_each(value, list) { - *element++ = *value; - } nxt_list_loop; - - nxt_mp_destroy(mp_temp); - - return p + 1; - -error: - - nxt_mp_destroy(mp_temp); - return NULL; -} - - -static u_char * -nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_json_value_t *value, - u_char *start, u_char *end) -{ - u_char *p, ch, *last, *s; - size_t size, surplus; - uint32_t utf, utf_high; - nxt_uint_t i; - enum { - sw_usual = 0, - sw_escape, - sw_encoded1, - sw_encoded2, - sw_encoded3, - sw_encoded4, - } state; - - start++; - - state = 0; - surplus = 0; - - for (p = start; nxt_fast_path(p != end); p++) { - ch = *p; - - switch (state) { - - case sw_usual: - - if (ch == '"') { - break; - } - - if (ch == '\\') { - state = sw_escape; - continue; - } - - if (nxt_fast_path(ch >= ' ')) { - continue; - } - - return NULL; - - case sw_escape: - - switch (ch) { - case '"': - case '\\': - case '/': - case 'n': - case 'r': - case 't': - case 'b': - case 'f': - surplus++; - state = sw_usual; - continue; - - case 'u': - /* - * Basic unicode 6 bytes "\uXXXX" in JSON - * and up to 3 bytes in UTF-8. - * - * Surrogate pair: 12 bytes "\uXXXX\uXXXX" in JSON - * and 3 or 4 bytes in UTF-8. - */ - surplus += 3; - state = sw_encoded1; - continue; - } - - return NULL; - - case sw_encoded1: - case sw_encoded2: - case sw_encoded3: - case sw_encoded4: - - if (nxt_fast_path((ch >= '0' && ch <= '9') - || (ch >= 'A' && ch <= 'F'))) - { - state = (state == sw_encoded4) ? sw_usual : state + 1; - continue; - } - - return NULL; - } - - break; - } - - if (nxt_slow_path(p == end)) { - return NULL; - } - - /* Points to the ending quote mark. */ - last = p; - - size = last - start - surplus; - - if (size > NXT_CONF_JSON_STR_SIZE) { - value->type = NXT_CONF_JSON_STRING; - value->u.string = nxt_str_alloc(mp, size); - - if (nxt_slow_path(value->u.string == NULL)) { - return NULL; - } - - s = value->u.string->start; - - } else { - value->type = NXT_CONF_JSON_SHORT_STRING; - value->u.str[0] = size; - - s = &value->u.str[1]; - } - - if (surplus == 0) { - nxt_memcpy(s, start, size); - return last + 1; - } - - p = start; - - do { - ch = *p++; - - if (ch != '\\') { - *s++ = ch; - continue; - } - - ch = *p++; - - switch (ch) { - case '"': - case '\\': - case '/': - *s++ = ch; - continue; - - case 'n': - *s++ = '\n'; - continue; - - case 'r': - *s++ = '\r'; - continue; - - case 't': - *s++ = '\t'; - continue; - - case 'b': - *s++ = '\b'; - continue; - - case 'f': - *s++ = '\f'; - continue; - } - - utf = 0; - utf_high = 0; - - for ( ;; ) { - for (i = 0; i < 4; i++) { - utf = (utf << 4) + (p[i] - (p[i] >= 'A' ? 'A' : '0')); - } - - p += 4; - - if (utf < 0xd800 || utf > 0xdbff || utf_high) { - break; - } - - utf_high = utf; - utf = 0; - - if (p[0] != '\\' || p[1] != 'u') { - break; - } - - p += 2; - } - - if (utf_high != 0) { - if (nxt_slow_path(utf_high < 0xd800 - || utf_high > 0xdbff - || utf < 0xdc00 - || utf > 0xdfff)) - { - /* Invalid surrogate pair. */ - return NULL; - } - - utf = ((utf_high - 0xd800) << 10) + (utf - 0xdc00); - } - - s = nxt_utf8_encode(s, utf); - - } while (p != last); - - if (size > NXT_CONF_JSON_STR_SIZE) { - value->u.string->length = s - value->u.string->start; - - } else { - value->u.str[0] = s - &value->u.str[1]; - } - - return last + 1; -} - - -static u_char * -nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_json_value_t *value, - u_char *start, u_char *end) -{ - u_char *p, ch; - uint64_t integer; - nxt_int_t sign; -#if 0 - uint64_t frac, power - nxt_int_t e, negative; -#endif - - static const uint64_t cutoff = NXT_INT64_T_MAX / 10; - static const uint64_t cutlim = NXT_INT64_T_MAX % 10; - - ch = *start; - - if (ch == '-') { - sign = -1; - start++; - - } else { - sign = 1; - } - - integer = 0; - - for (p = start; nxt_fast_path(p != end); p++) { - ch = *p; - - /* Values below '0' become >= 208. */ - ch = ch - '0'; - - if (ch > 9) { - break; - } - - if (nxt_slow_path(integer >= cutoff - && (integer > cutoff || ch > cutlim))) - { - return NULL; - } - - integer = integer * 10 + ch; - } - - if (nxt_slow_path(p == start || (p - start > 1 && *start == '0'))) { - return NULL; - } - - if (ch != '.') { - value->type = NXT_CONF_JSON_INTEGER; - value->u.integer = sign * integer; - return p; - } - -#if 0 - start = p + 1; - - frac = 0; - power = 1; - - for (p = start; nxt_fast_path(p != end); p++) { - ch = *p; - - /* Values below '0' become >= 208. */ - ch = ch - '0'; - - if (ch > 9) { - break; - } - - if (nxt_slow_path((frac >= cutoff && (frac > cutoff || ch > cutlim)) - || power > cutoff)) - { - return NULL; - } - - frac = frac * 10 + ch; - power *= 10; - } - - if (nxt_slow_path(p == start)) { - return NULL; - } - - value->type = NXT_CONF_JSON_NUMBER; - value->u.number = integer + (double) frac / power; - - value->u.number = copysign(value->u.number, sign); - - if (ch == 'e' || ch == 'E') { - start = p + 1; - - ch = *start; - - if (ch == '-' || ch == '+') { - start++; - } - - negative = (ch == '-') ? 1 : 0; - e = 0; - - for (p = start; nxt_fast_path(p != end); p++) { - ch = *p; - - /* Values below '0' become >= 208. */ - ch = ch - '0'; - - if (ch > 9) { - break; - } - - e = e * 10 + ch; - - if (nxt_slow_path(e > DBL_MAX_10_EXP)) { - return NULL; - } - } - - if (nxt_slow_path(p == start)) { - return NULL; - } - - if (negative) { - value->u.number /= exp10(e); - - } else { - value->u.number *= exp10(e); - } - } - - if (nxt_fast_path(isfinite(value->u.number))) { - return p; - } -#endif - - return NULL; -} - - -size_t -nxt_conf_json_value_length(nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - switch (value->type) { - - case NXT_CONF_JSON_NULL: - return sizeof("null") - 1; - - case NXT_CONF_JSON_BOOLEAN: - return value->u.boolean ? sizeof("true") - 1 : sizeof("false") - 1; - - case NXT_CONF_JSON_INTEGER: - return nxt_conf_json_integer_length(value); - - case NXT_CONF_JSON_NUMBER: - /* TODO */ - return 0; - - case NXT_CONF_JSON_SHORT_STRING: - case NXT_CONF_JSON_STRING: - return nxt_conf_json_string_length(value); - - case NXT_CONF_JSON_ARRAY: - return nxt_conf_json_array_length(value, pretty); - - case NXT_CONF_JSON_OBJECT: - return nxt_conf_json_object_length(value, pretty); - } - - nxt_unreachable(); - - return 0; -} - - -u_char * -nxt_conf_json_value_print(u_char *p, nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - switch (value->type) { - - case NXT_CONF_JSON_NULL: - return nxt_cpymem(p, "null", 4); - - case NXT_CONF_JSON_BOOLEAN: - return value->u.boolean ? nxt_cpymem(p, "true", 4) - : nxt_cpymem(p, "false", 5); - - case NXT_CONF_JSON_INTEGER: - return nxt_conf_json_integer_print(p, value); - - case NXT_CONF_JSON_NUMBER: - /* TODO */ - return p; - - case NXT_CONF_JSON_SHORT_STRING: - case NXT_CONF_JSON_STRING: - return nxt_conf_json_string_print(p, value); - - case NXT_CONF_JSON_ARRAY: - return nxt_conf_json_array_print(p, value, pretty); - - case NXT_CONF_JSON_OBJECT: - return nxt_conf_json_object_print(p, value, pretty); - } - - nxt_unreachable(); - - return p; -} - - -static size_t -nxt_conf_json_integer_length(nxt_conf_json_value_t *value) -{ - int64_t num; - - num = llabs(value->u.integer); - - if (num <= 9999) { - return sizeof("-9999") - 1; - } - - if (num <= 99999999999) { - return sizeof("-99999999999") - 1; - } - - return NXT_INT64_T_LEN; -} - - -static u_char * -nxt_conf_json_integer_print(u_char *p, nxt_conf_json_value_t *value) -{ - return nxt_sprintf(p, p + NXT_INT64_T_LEN, "%L", value->u.integer); -} - - -static size_t -nxt_conf_json_string_length(nxt_conf_json_value_t *value) -{ - nxt_str_t str; - - nxt_conf_json_value_get_string(value, &str); - - return 2 + nxt_conf_json_escape_length(str.start, str.length); -} - - -static u_char * -nxt_conf_json_string_print(u_char *p, nxt_conf_json_value_t *value) -{ - nxt_str_t str; - - nxt_conf_json_value_get_string(value, &str); - - *p++ = '"'; - - p = nxt_conf_json_escape(p, str.start, str.length); - - *p++ = '"'; - - return p; -} - - -static size_t -nxt_conf_json_array_length(nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - size_t len; - nxt_uint_t n; - nxt_conf_json_array_t *array; - - array = value->u.array; - - /* [] */ - len = 2; - - if (pretty != NULL) { - pretty->level++; - } - - value = array->elements; - - for (n = 0; n < array->count; n++) { - len += nxt_conf_json_value_length(&value[n], pretty); - - if (pretty != NULL) { - /* Indentation and new line. */ - len += pretty->level + 2; - } - } - - if (pretty != NULL) { - pretty->level--; - - if (n != 0) { - /* Indentation and new line. */ - len += pretty->level + 2; - } - } - - /* Reserve space for "n" commas. */ - return len + n; -} - - -static u_char * -nxt_conf_json_array_print(u_char *p, nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - nxt_uint_t n; - nxt_conf_json_array_t *array; - - array = value->u.array; - - *p++ = '['; - - if (array->count != 0) { - value = array->elements; - - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - - pretty->level++; - p = nxt_conf_json_indentation(p, pretty->level); - } - - p = nxt_conf_json_value_print(p, &value[0], pretty); - - for (n = 1; n < array->count; n++) { - *p++ = ','; - - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - p = nxt_conf_json_indentation(p, pretty->level); - - pretty->more_space = 0; - } - - p = nxt_conf_json_value_print(p, &value[n], pretty); - } - - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - - pretty->level--; - p = nxt_conf_json_indentation(p, pretty->level); - - pretty->more_space = 1; - } - } - - *p++ = ']'; - - return p; -} - - -static size_t -nxt_conf_json_object_length(nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - size_t len; - nxt_uint_t n; - nxt_conf_json_object_t *object; - nxt_conf_json_obj_member_t *member; - - object = value->u.object; - - /* {} */ - len = 2; - - if (pretty != NULL) { - pretty->level++; - } - - member = object->members; - - for (n = 0; n < object->count; n++) { - len += nxt_conf_json_string_length(&member[n].name) + 1 - + nxt_conf_json_value_length(&member[n].value, pretty) + 1; - - if (pretty != NULL) { - /* - * Indentation, space after ":", new line, and possible - * additional empty line between non-empty objects. - */ - len += pretty->level + 1 + 2 + 2; - } - } - - if (pretty != NULL) { - pretty->level--; - - /* Indentation and new line. */ - len += pretty->level + 2; - } - - return len; -} - - -static u_char * -nxt_conf_json_object_print(u_char *p, nxt_conf_json_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - nxt_uint_t n; - nxt_conf_json_object_t *object; - nxt_conf_json_obj_member_t *member; - - object = value->u.object; - - *p++ = '{'; - - if (object->count != 0) { - - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - pretty->level++; - } - - member = object->members; - - n = 0; - - for ( ;; ) { - if (pretty != NULL) { - p = nxt_conf_json_indentation(p, pretty->level); - } - - p = nxt_conf_json_string_print(p, &member[n].name); - - *p++ = ':'; - - if (pretty != NULL) { - *p++ = ' '; - } - - p = nxt_conf_json_value_print(p, &member[n].value, pretty); - - n++; - - if (n == object->count) { - break; - } - - *p++ = ','; - - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - - if (pretty->more_space) { - pretty->more_space = 0; - p = nxt_conf_json_newline(p); - } - } - } - - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - - pretty->level--; - p = nxt_conf_json_indentation(p, pretty->level); - - pretty->more_space = 1; - } - } - - *p++ = '}'; - - return p; -} - - -static size_t -nxt_conf_json_escape_length(u_char *p, size_t size) -{ - u_char ch; - size_t len; - - len = size; - - while (size) { - ch = *p++; - - if (ch == '\\' || ch == '"') { - len++; - - } else if (ch <= 0x1f) { - - switch (ch) { - case '\n': - case '\r': - case '\t': - case '\b': - case '\f': - len++; - break; - - default: - len += sizeof("\\u001F") - 2; - } - } - - size--; - } - - return len; -} - - -static u_char * -nxt_conf_json_escape(u_char *dst, u_char *src, size_t size) -{ - u_char ch; - - while (size) { - ch = *src++; - - if (ch > 0x1f) { - - if (ch == '\\' || ch == '"') { - *dst++ = '\\'; - } - - *dst++ = ch; - - } else { - *dst++ = '\\'; - - switch (ch) { - case '\n': - *dst++ = 'n'; - break; - - case '\r': - *dst++ = 'r'; - break; - - case '\t': - *dst++ = 't'; - break; - - case '\b': - *dst++ = 'b'; - break; - - case '\f': - *dst++ = 'f'; - break; - - default: - *dst++ = 'u'; *dst++ = '0'; *dst++ = '0'; - *dst++ = '0' + (ch >> 4); - - ch &= 0xf; - - *dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10); - } - } - - size--; - } - - return dst; -} |