diff options
Diffstat (limited to 'src/libs/zbxjson/json.c')
-rw-r--r-- | src/libs/zbxjson/json.c | 316 |
1 files changed, 166 insertions, 150 deletions
diff --git a/src/libs/zbxjson/json.c b/src/libs/zbxjson/json.c index 6215e97db2e..c8422cde6a6 100644 --- a/src/libs/zbxjson/json.c +++ b/src/libs/zbxjson/json.c @@ -38,18 +38,17 @@ static char zbx_json_strerror_message[ZBX_JSON_MAX_STRERROR]; const char *zbx_json_strerror(void) { - zbx_json_strerror_message[ZBX_JSON_MAX_STRERROR - 1] = '\0'; /* force terminate string */ - return (&zbx_json_strerror_message[0]); + return zbx_json_strerror_message; } #ifdef HAVE___VA_ARGS__ # define zbx_set_json_strerror(fmt, ...) __zbx_zbx_set_json_strerror(ZBX_CONST_STRING(fmt), ##__VA_ARGS__) #else # define zbx_set_json_strerror __zbx_zbx_set_json_strerror -#endif /* HAVE___VA_ARGS__ */ +#endif static void __zbx_zbx_set_json_strerror(const char *fmt, ...) { - va_list args; + va_list args; va_start(args, fmt); @@ -553,166 +552,158 @@ const char *zbx_json_next(const struct zbx_json_parse *jp, const char *p) return NULL; } -static size_t zbx_json_string_size(const char *p) -{ - int state = 0; /* 0 - init; 1 - inside string */ - size_t sz = 0; - - if ('"' != *p) - return (size_t)(-1); - - while ('\0' != *p) /* this should never happen */ - { - if (*p == '"') - { - if (state == 1) - return sz; - state = 1; - } - else if (state == 1) - { - if (*p == '\\' && 'u' == *++p) - p += 4; - sz++; - } - p++; - } - - return (size_t)(-1); -} - -static const char *zbx_json_decodestring(const char *p, char *string, size_t len) +static const char *zbx_json_decodenull(const char *p) { - int state = 0; /* 0 - init; 1 - inside string */ - char *o = string; - u_char c; - - if ('"' != *p) - return NULL; - - while ('\0' != *p) /* this should never happen */ - { - if (*p == '"') - { - if (state == 1) - { - *o = '\0'; - return ++p; - } - state = 1; - } - else if (state == 1 && (size_t)(o - string) < len - 1/*'\0'*/) - { - if (*p == '\\') - { - switch (*++p) - { - case 'b': - *o++ = '\b'; - break; - case 'f': - *o++ = '\f'; - break; - case 'n': - *o++ = '\n'; - break; - case 'r': - *o++ = '\r'; - break; - case 't': - *o++ = '\t'; - break; - case 'u': - p += 3; /* "u00" */ - c = zbx_hex2num(*p++) << 4; - c += zbx_hex2num(*p); - *o++ = (char)c; - break; - default: - *o++ = *p; - } - } - else - *o++ = *p; - } - - p++; - } + if ('n' == p[0] && 'u' == p[1] && 'l' == p[2] && 'l' == p[3]) + return p + 4; return NULL; } -static size_t zbx_json_int_size(const char *p) +/****************************************************************************** + * * + * Function: zbx_json_decode_character * + * * + * Purpose: decodes escape character * + * * + * Parameters: p - [IN/OUT] a pointer to the next character in string * + * * + * Return value: 0 - invalid escape character * + * !0 - the escaped character * + * * + ******************************************************************************/ +static char zbx_json_decode_character(const char **p) { - size_t sz = 0; + char out; - while (*p != '\0') /* this should never happen */ + switch (*(++*p)) { - if ((*p < '0' || *p > '9') && *p != '-') - return sz; - else - sz++; - p++; + case '"': + out = '"'; + break; + case '\\': + out = '\\'; + break; + case '/': + out = '/'; + break; + case 'b': + out = '\b'; + break; + case 'f': + out = '\f'; + break; + case 'n': + out = '\n'; + break; + case 'r': + out = '\r'; + break; + case 't': + out = '\t'; + break; + case 'u': + *p += 3; /* "u00" */ + out = zbx_hex2num(**p) << 4; + out += zbx_hex2num(*(++*p)); + break; + default: + THIS_SHOULD_NEVER_HAPPEN; + return '\0'; } - return (size_t)(-1); + ++*p; + + return out; } -static const char *zbx_json_decodeint(const char *p, char *string, size_t len) +/****************************************************************************** + * * + * Function: zbx_json_copy_string * + * * + * Purpose: copies json name/string value by omitting leading/trailing " and * + * converting escape sequences * + * * + * Parameters: p - [IN] a pointer to the next character in string * + * out - [OUT] the output buffer * + * size - [IN] the output buffer size * + * * + * Return value: A pointer to the next character in input string or NULL if * + * string copying failed. * + * * + ******************************************************************************/ +static const char *zbx_json_copy_string(const char *p, char *out, size_t size) { - char *o = string; + char *start = out; + + p++; - while ('\0' != *p) /* this should never happen */ + while ('\0' != *p && out - start < size - 1) { - if ((*p < '0' || *p > '9') && *p != '-') - { - *o = '\0'; - return p; - } - else if ((size_t)(o - string) < len - 1/*'\0'*/) + switch (*p) { - *o++ = *p; + case '\\': + if ('\0' != (*out = zbx_json_decode_character(&p))) + out++; + break; + case '"': + *out = '\0'; + return ++p; + default: + *out++ = *p++; } - - p++; } return NULL; } -static const char *zbx_json_decodenull(const char *p) -{ - if ('n' == p[0] && 'u' == p[1] && 'l' == p[2] && 'l' == p[3]) - return p + 4; - - return NULL; -} - -static size_t zbx_json_value_size(const char *p, zbx_json_type_t jt) +/****************************************************************************** + * * + * Function: zbx_json_copy_value * + * * + * Purpose: copies json value * + * * + * Parameters: p - [IN] a pointer to the next character in string * + * len - [IN] the value length * + * out - [OUT] the output buffer * + * size - [IN] the output buffer size * + * * + * Return value: A pointer to the next character in input string or NULL if * + * string copying failed. * + * * + * Comments: String values are converted (leading/trailing " dropped and * + * escape sequences translated) while other values are simply * + * copied. * + * * + ******************************************************************************/ +static const char *zbx_json_copy_value(const char *p, size_t len, char *out, size_t size) { - switch (jt) + if (ZBX_JSON_TYPE_STRING == __zbx_json_type(p)) { - case ZBX_JSON_TYPE_STRING: - return zbx_json_string_size(p); - case ZBX_JSON_TYPE_INT: - return zbx_json_int_size(p); - default: - return (size_t)(-1); + if (NULL == zbx_json_copy_string(p, out, size)) + return NULL; } + else + zbx_strlcpy(out, p, MIN(size, len + 1)); + + return p + len; } -static const char *zbx_json_decodevalue(const char *p, char *string, size_t len, int *is_null) +static const char *zbx_json_decodevalue(const char *p, char *string, size_t size, int *is_null) { + size_t len; + switch (__zbx_json_type(p)) { case ZBX_JSON_TYPE_STRING: - if (NULL != is_null) - *is_null = 0; - return zbx_json_decodestring(p, string, len); case ZBX_JSON_TYPE_INT: if (NULL != is_null) *is_null = 0; - return zbx_json_decodeint(p, string, len); + + if (0 == (len = json_parse_value(p, NULL))) + return NULL; + + return zbx_json_copy_value(p, len, string, size); case ZBX_JSON_TYPE_NULL: if (NULL != is_null) *is_null = 1; @@ -723,28 +714,40 @@ static const char *zbx_json_decodevalue(const char *p, char *string, size_t len, } } -static const char *zbx_json_decodevalue_dyn(const char *p, char **string, size_t *string_alloc) +static const char *zbx_json_decodevalue_dyn(const char *p, char **string, size_t *string_alloc, int *is_null) { - zbx_json_type_t jt; - size_t sz; - - jt = __zbx_json_type(p); - - if ((size_t)(-1) == (sz = zbx_json_value_size(p, jt))) - return NULL; + size_t len; - if (*string_alloc <= sz) - { - *string_alloc = sz + 1; - *string = zbx_realloc(*string, *string_alloc); - } - - switch (jt) + switch (__zbx_json_type(p)) { case ZBX_JSON_TYPE_STRING: - return zbx_json_decodestring(p, *string, *string_alloc); case ZBX_JSON_TYPE_INT: - return zbx_json_decodeint(p, *string, *string_alloc); + if (NULL != is_null) + *is_null = 0; + + if (0 == (len = json_parse_value(p, NULL))) + return NULL; + + if (*string_alloc <= len) + { + *string_alloc = len + 1; + *string = zbx_realloc(*string, *string_alloc); + } + + return zbx_json_copy_value(p, len, *string, *string_alloc); + case ZBX_JSON_TYPE_NULL: + if (NULL != is_null) + *is_null = 1; + + if (*string_alloc < 1) + { + *string_alloc = 1; + *string = zbx_realloc(*string, *string_alloc); + } + + **string = '\0'; + + return zbx_json_decodenull(p); default: return NULL; } @@ -758,7 +761,7 @@ const char *zbx_json_pair_next(const struct zbx_json_parse *jp, const char *p, c if (ZBX_JSON_TYPE_STRING != __zbx_json_type(p)) return NULL; - if (NULL == (p = zbx_json_decodestring(p, name, len))) + if (NULL == (p = zbx_json_copy_string(p, name, len))) return NULL; SKIP_WHITESPACE(p); @@ -815,6 +818,20 @@ const char *zbx_json_next_value(const struct zbx_json_parse *jp, const char *p, /****************************************************************************** * * + * Function: zbx_json_next_value_dyn * + * * + ******************************************************************************/ +const char *zbx_json_next_value_dyn(const struct zbx_json_parse *jp, const char *p, char **string, + size_t *string_alloc, int *is_null) +{ + if (NULL == (p = zbx_json_next(jp, p))) + return NULL; + + return zbx_json_decodevalue_dyn(p, string, string_alloc, is_null); +} + +/****************************************************************************** + * * * Function: zbx_json_value_by_name * * * * Purpose: return value by pair name * @@ -855,7 +872,7 @@ int zbx_json_value_by_name_dyn(const struct zbx_json_parse *jp, const char *name if (NULL == (p = zbx_json_pair_by_name(jp, name))) return FAIL; - if (NULL == zbx_json_decodevalue_dyn(p, string, string_alloc)) + if (NULL == zbx_json_decodevalue_dyn(p, string, string_alloc, NULL)) return FAIL; return SUCCEED; @@ -943,4 +960,3 @@ int zbx_json_count(const struct zbx_json_parse *jp) return num; } - |