jansson update. 2.11 to 2.12 (#724)

This commit is contained in:
Oleg Moiseenko 2018-11-30 09:43:46 +02:00 committed by pwpiwi
commit 6a2bd85719
10 changed files with 190 additions and 151 deletions

View file

@ -61,8 +61,8 @@ static int dump_to_file(const char *buffer, size_t size, void *data)
static int dump_to_fd(const char *buffer, size_t size, void *data) static int dump_to_fd(const char *buffer, size_t size, void *data)
{ {
int *dest = (int *)data;
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
int *dest = (int *)data;
if(write(*dest, buffer, size) == (ssize_t)size) if(write(*dest, buffer, size) == (ssize_t)size)
return 0; return 0;
#endif #endif
@ -101,7 +101,7 @@ static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t
static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags) static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags)
{ {
const char *pos, *end, *lim; const char *pos, *end, *lim;
int32_t codepoint; int32_t codepoint = 0;
if(dump("\"", 1, data)) if(dump("\"", 1, data))
return -1; return -1;
@ -306,7 +306,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
const char *separator; const char *separator;
int separator_length; int separator_length;
/* Space for "0x", double the sizeof a pointer for the hex and a terminator. */ /* Space for "0x", double the sizeof a pointer for the hex and a terminator. */
char key[2 + (sizeof(json) * 2) + 1]; char loop_key[2 + (sizeof(json) * 2) + 1];
if(flags & JSON_COMPACT) { if(flags & JSON_COMPACT) {
separator = ":"; separator = ":";
@ -318,7 +318,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
} }
/* detect circular references */ /* detect circular references */
if (loop_check(parents, json, key, sizeof(key))) if (loop_check(parents, json, loop_key, sizeof(loop_key)))
return -1; return -1;
iter = json_object_iter((json_t *)json); iter = json_object_iter((json_t *)json);
@ -326,7 +326,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
if(!embed && dump("{", 1, data)) if(!embed && dump("{", 1, data))
return -1; return -1;
if(!iter) { if(!iter) {
hashtable_del(parents, key); hashtable_del(parents, loop_key);
return embed ? 0 : dump("}", 1, data); return embed ? 0 : dump("}", 1, data);
} }
if(dump_indent(flags, depth + 1, 0, dump, data)) if(dump_indent(flags, depth + 1, 0, dump, data))
@ -422,7 +422,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
} }
} }
hashtable_del(parents, key); hashtable_del(parents, loop_key);
return embed ? 0 : dump("}", 1, data); return embed ? 0 : dump("}", 1, data);
} }

View file

@ -55,7 +55,7 @@ typedef struct hashtable {
* *
* Returns 0 on success, -1 on error (out of memory). * Returns 0 on success, -1 on error (out of memory).
*/ */
int hashtable_init(hashtable_t *hashtable); int hashtable_init(hashtable_t *hashtable) JANSSON_ATTRS(warn_unused_result);
/** /**
* hashtable_close - Release all resources used by a hashtable object * hashtable_close - Release all resources used by a hashtable object

View file

@ -164,7 +164,7 @@ static int seed_from_timestamp_and_pid(uint32_t *seed) {
} }
static uint32_t generate_seed() { static uint32_t generate_seed() {
uint32_t seed; uint32_t seed = 0;
int done = 0; int done = 0;
#if !defined(_WIN32) && defined(USE_URANDOM) #if !defined(_WIN32) && defined(USE_URANDOM)

View file

@ -9,7 +9,6 @@
#define JANSSON_H #define JANSSON_H
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdlib.h> /* for size_t */ #include <stdlib.h> /* for size_t */
#include <stdarg.h> #include <stdarg.h>
@ -22,11 +21,11 @@ extern "C" {
/* version */ /* version */
#define JANSSON_MAJOR_VERSION 2 #define JANSSON_MAJOR_VERSION 2
#define JANSSON_MINOR_VERSION 11 #define JANSSON_MINOR_VERSION 12
#define JANSSON_MICRO_VERSION 0 #define JANSSON_MICRO_VERSION 0
/* Micro version is omitted if it's 0 */ /* Micro version is omitted if it's 0 */
#define JANSSON_VERSION "2.11" #define JANSSON_VERSION "2.12"
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this /* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */ for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
@ -40,6 +39,12 @@ extern "C" {
#define JANSSON_THREAD_SAFE_REFCOUNT 1 #define JANSSON_THREAD_SAFE_REFCOUNT 1
#endif #endif
#if defined(__GNUC__) || defined(__clang__)
#define JANSSON_ATTRS(...) __attribute__((__VA_ARGS__))
#else
#define JANSSON_ATTRS(...)
#endif
/* types */ /* types */
typedef enum { typedef enum {
@ -186,7 +191,7 @@ static JSON_INLINE enum json_error_code json_error_code(const json_error_t *e) {
void json_object_seed(size_t seed); void json_object_seed(size_t seed);
size_t json_object_size(const json_t *object); size_t json_object_size(const json_t *object);
json_t *json_object_get(const json_t *object, const char *key); json_t *json_object_get(const json_t *object, const char *key) JANSSON_ATTRS(warn_unused_result);
int json_object_set_new(json_t *object, const char *key, json_t *value); int json_object_set_new(json_t *object, const char *key, json_t *value);
int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value); int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value);
int json_object_del(json_t *object, const char *key); int json_object_del(json_t *object, const char *key);
@ -238,7 +243,7 @@ int json_object_iter_set(json_t *object, void *iter, json_t *value)
} }
size_t json_array_size(const json_t *array); size_t json_array_size(const json_t *array);
json_t *json_array_get(const json_t *array, size_t index); json_t *json_array_get(const json_t *array, size_t index) JANSSON_ATTRS(warn_unused_result);
int json_array_set_new(json_t *array, size_t index, json_t *value); int json_array_set_new(json_t *array, size_t index, json_t *value);
int json_array_append_new(json_t *array, json_t *value); int json_array_append_new(json_t *array, json_t *value);
int json_array_insert_new(json_t *array, size_t index, json_t *value); int json_array_insert_new(json_t *array, size_t index, json_t *value);
@ -279,9 +284,9 @@ int json_real_set(json_t *real, double value);
/* pack, unpack */ /* pack, unpack */
json_t *json_pack(const char *fmt, ...); json_t *json_pack(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result);
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...); json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) JANSSON_ATTRS(warn_unused_result);
json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap); json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result);
#define JSON_VALIDATE_ONLY 0x1 #define JSON_VALIDATE_ONLY 0x1
#define JSON_STRICT 0x2 #define JSON_STRICT 0x2
@ -292,8 +297,8 @@ int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char
/* sprintf */ /* sprintf */
json_t *json_sprintf(const char *fmt, ...); json_t *json_sprintf(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 2));
json_t *json_vsprintf(const char *fmt, va_list ap); json_t *json_vsprintf(const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 0));
/* equality */ /* equality */
@ -303,10 +308,8 @@ int json_equal(const json_t *value1, const json_t *value2);
/* copying */ /* copying */
json_t *json_copy(json_t *value); json_t *json_copy(json_t *value) JANSSON_ATTRS(warn_unused_result);
json_t *json_deep_copy(const json_t *value); json_t *json_deep_copy(const json_t *value) JANSSON_ATTRS(warn_unused_result);
/* path */
json_t *json_path_get(const json_t *json, const char *path); json_t *json_path_get(const json_t *json, const char *path);
int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error); int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error);
@ -327,12 +330,12 @@ int json_path_set(json_t *json, const char *path, json_t *value, size_t flags, j
typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
json_t *json_loads(const char *input, size_t flags, json_error_t *error); json_t *json_loads(const char *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error); json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
json_t *json_loadf(FILE *input, size_t flags, json_error_t *error); json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
json_t *json_loadfd(int input, size_t flags, json_error_t *error); json_t *json_loadfd(int input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
json_t *json_load_file(const char *path, size_t flags, json_error_t *error); json_t *json_load_file(const char *path, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error); json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
/* encoding */ /* encoding */
@ -350,7 +353,7 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
char *json_dumps(const json_t *json, size_t flags); char *json_dumps(const json_t *json, size_t flags) JANSSON_ATTRS(warn_unused_result);
size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags); size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags);
int json_dumpf(const json_t *json, FILE *output, size_t flags); int json_dumpf(const json_t *json, FILE *output, size_t flags);
int json_dumpfd(const json_t *json, int output, size_t flags); int json_dumpfd(const json_t *json, int output, size_t flags);

View file

@ -87,11 +87,11 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out);
int jsonp_dtostr(char *buffer, size_t size, double value, int prec); int jsonp_dtostr(char *buffer, size_t size, double value, int prec);
/* Wrappers for custom memory functions */ /* Wrappers for custom memory functions */
void* jsonp_malloc(size_t size); void* jsonp_malloc(size_t size) JANSSON_ATTRS(warn_unused_result);
void jsonp_free(void *ptr); void jsonp_free(void *ptr);
char *jsonp_strndup(const char *str, size_t length); char *jsonp_strndup(const char *str, size_t length) JANSSON_ATTRS(warn_unused_result);
char *jsonp_strdup(const char *str); char *jsonp_strdup(const char *str) JANSSON_ATTRS(warn_unused_result);
char *jsonp_strndup(const char *str, size_t len); char *jsonp_strndup(const char *str, size_t len) JANSSON_ATTRS(warn_unused_result);
/* Windows compatibility */ /* Windows compatibility */

View file

@ -829,10 +829,8 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
} }
json = jsonp_stringn_nocheck_own(value, len); json = jsonp_stringn_nocheck_own(value, len);
if(json) { lex->value.string.val = NULL;
lex->value.string.val = NULL; lex->value.string.len = 0;
lex->value.string.len = 0;
}
break; break;
} }
@ -1036,8 +1034,8 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
static int fd_get_func(int *fd) static int fd_get_func(int *fd)
{ {
uint8_t c;
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
uint8_t c;
if (read(*fd, &c, 1) == 1) if (read(*fd, &c, 1) == 1)
return c; return c;
#endif #endif

View file

@ -75,6 +75,9 @@ static void next_token(scanner_t *s)
return; return;
} }
if (!token(s) && !*s->fmt)
return;
t = s->fmt; t = s->fmt;
s->column++; s->column++;
s->pos++; s->pos++;
@ -97,7 +100,7 @@ static void next_token(scanner_t *s)
s->token.column = s->column; s->token.column = s->column;
s->token.pos = s->pos; s->token.pos = s->pos;
t++; if (*t) t++;
s->fmt = t; s->fmt = t;
} }
@ -127,7 +130,7 @@ static json_t *pack(scanner_t *s, va_list *ap);
/* ours will be set to 1 if jsonp_free() must be called for the result /* ours will be set to 1 if jsonp_free() must be called for the result
afterwards */ afterwards */
static char *read_string(scanner_t *s, va_list *ap, static char *read_string(scanner_t *s, va_list *ap,
const char *purpose, size_t *out_len, int *ours) const char *purpose, size_t *out_len, int *ours, int optional)
{ {
char t; char t;
strbuffer_t strbuff; strbuffer_t strbuff;
@ -144,7 +147,10 @@ static char *read_string(scanner_t *s, va_list *ap,
str = va_arg(*ap, const char *); str = va_arg(*ap, const char *);
if(!str) { if(!str) {
set_error(s, "<args>", json_error_null_value, "NULL string argument"); if (!optional) {
set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
s->has_error = 1;
}
return NULL; return NULL;
} }
@ -152,19 +158,28 @@ static char *read_string(scanner_t *s, va_list *ap,
if(!utf8_check_string(str, length)) { if(!utf8_check_string(str, length)) {
set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose); set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
s->has_error = 1;
return NULL; return NULL;
} }
*out_len = length; *out_len = length;
return (char *)str; return (char *)str;
} else if (optional) {
set_error(s, "<format>", json_error_invalid_format, "Cannot use '%c' on optional strings", t);
s->has_error = 1;
return NULL;
} }
strbuffer_init(&strbuff); if(strbuffer_init(&strbuff)) {
set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
s->has_error = 1;
}
while(1) { while(1) {
str = va_arg(*ap, const char *); str = va_arg(*ap, const char *);
if(!str) { if(!str) {
set_error(s, "<args>", json_error_null_value, "NULL string argument"); set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
s->has_error = 1; s->has_error = 1;
} }
@ -220,6 +235,7 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
size_t len; size_t len;
int ours; int ours;
json_t *value; json_t *value;
char valueOptional;
if(!token(s)) { if(!token(s)) {
set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string"); set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
@ -231,20 +247,21 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
goto error; goto error;
} }
key = read_string(s, ap, "object key", &len, &ours); key = read_string(s, ap, "object key", &len, &ours, 0);
if (!key)
s->has_error = 1;
next_token(s); next_token(s);
next_token(s);
valueOptional = token(s);
prev_token(s);
value = pack(s, ap); value = pack(s, ap);
if(!value) { if(!value) {
if(ours) if(ours)
jsonp_free(key); jsonp_free(key);
if(strchr("soO", token(s)) && s->next_token.token == '*') { if(valueOptional != '*') {
next_token(s); set_error(s, "<args>", json_error_null_value, "NULL object value");
} else {
s->has_error = 1; s->has_error = 1;
} }
@ -263,8 +280,6 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
if(ours) if(ours)
jsonp_free(key); jsonp_free(key);
if(strchr("soO", token(s)) && s->next_token.token == '*')
next_token(s);
next_token(s); next_token(s);
} }
@ -283,6 +298,7 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
while(token(s) != ']') { while(token(s) != ']') {
json_t *value; json_t *value;
char valueOptional;
if(!token(s)) { if(!token(s)) {
set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string"); set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
@ -290,11 +306,13 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
goto error; goto error;
} }
next_token(s);
valueOptional = token(s);
prev_token(s);
value = pack(s, ap); value = pack(s, ap);
if(!value) { if(!value) {
if(strchr("soO", token(s)) && s->next_token.token == '*') { if(valueOptional != '*') {
next_token(s);
} else {
s->has_error = 1; s->has_error = 1;
} }
@ -310,8 +328,6 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
s->has_error = 1; s->has_error = 1;
} }
if(strchr("soO", token(s)) && s->next_token.token == '*')
next_token(s);
next_token(s); next_token(s);
} }
@ -326,23 +342,97 @@ error:
static json_t *pack_string(scanner_t *s, va_list *ap) static json_t *pack_string(scanner_t *s, va_list *ap)
{ {
char *str; char *str;
char t;
size_t len; size_t len;
int ours; int ours;
int nullable; int optional;
next_token(s); next_token(s);
nullable = token(s) == '?'; t = token(s);
if (!nullable) optional = t == '?' || t == '*';
if (!optional)
prev_token(s); prev_token(s);
str = read_string(s, ap, "string", &len, &ours); str = read_string(s, ap, "string", &len, &ours, optional);
if (!str) {
return nullable ? json_null() : NULL; if (!str)
} else if (ours) { return t == '?' && !s->has_error ? json_null() : NULL;
return jsonp_stringn_nocheck_own(str, len);
} else { if (s->has_error) {
return json_stringn_nocheck(str, len); /* It's impossible to reach this point if ours != 0, do not free str. */
return NULL;
} }
if (ours)
return jsonp_stringn_nocheck_own(str, len);
return json_stringn_nocheck(str, len);
}
static json_t *pack_object_inter(scanner_t *s, va_list *ap, int need_incref)
{
json_t *json;
char ntoken;
next_token(s);
ntoken = token(s);
if (ntoken != '?' && ntoken != '*')
prev_token(s);
json = va_arg(*ap, json_t *);
if (json)
return need_incref ? json_incref(json) : json;
switch (ntoken) {
case '?':
return json_null();
case '*':
return NULL;
default:
break;
}
set_error(s, "<args>", json_error_null_value, "NULL object");
s->has_error = 1;
return NULL;
}
static json_t *pack_integer(scanner_t *s, json_int_t value)
{
json_t *json = json_integer(value);
if (!json) {
set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
s->has_error = 1;
}
return json;
}
static json_t *pack_real(scanner_t *s, double value)
{
/* Allocate without setting value so we can identify OOM error. */
json_t *json = json_real(0.0);
if (!json) {
set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
s->has_error = 1;
return NULL;
}
if (json_real_set(json, value)) {
json_decref(json);
set_error(s, "<args>", json_error_numeric_overflow, "Invalid floating point value");
s->has_error = 1;
return NULL;
}
return json;
} }
static json_t *pack(scanner_t *s, va_list *ap) static json_t *pack(scanner_t *s, va_list *ap)
@ -364,49 +454,19 @@ static json_t *pack(scanner_t *s, va_list *ap)
return va_arg(*ap, int) ? json_true() : json_false(); return va_arg(*ap, int) ? json_true() : json_false();
case 'i': /* integer from int */ case 'i': /* integer from int */
return json_integer(va_arg(*ap, int)); return pack_integer(s, va_arg(*ap, int));
case 'I': /* integer from json_int_t */ case 'I': /* integer from json_int_t */
return json_integer(va_arg(*ap, json_int_t)); return pack_integer(s, va_arg(*ap, json_int_t));
case 'f': /* real */ case 'f': /* real */
return json_real(va_arg(*ap, double)); return pack_real(s, va_arg(*ap, double));
case 'O': /* a json_t object; increments refcount */ case 'O': /* a json_t object; increments refcount */
{ return pack_object_inter(s, ap, 1);
int nullable;
json_t *json;
next_token(s);
nullable = token(s) == '?';
if (!nullable)
prev_token(s);
json = va_arg(*ap, json_t *);
if (!json && nullable) {
return json_null();
} else {
return json_incref(json);
}
}
case 'o': /* a json_t object; doesn't increment refcount */ case 'o': /* a json_t object; doesn't increment refcount */
{ return pack_object_inter(s, ap, 0);
int nullable;
json_t *json;
next_token(s);
nullable = token(s) == '?';
if (!nullable)
prev_token(s);
json = va_arg(*ap, json_t *);
if (!json && nullable) {
return json_null();
} else {
return json;
}
}
default: default:
set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'", set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'",
@ -508,48 +568,34 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
if(root && strict == 1) { if(root && strict == 1) {
/* We need to check that all non optional items have been parsed */ /* We need to check that all non optional items have been parsed */
const char *key; const char *key;
int have_unrecognized_keys = 0; /* keys_res is 1 for uninitialized, 0 for success, -1 for error. */
int keys_res = 1;
strbuffer_t unrecognized_keys; strbuffer_t unrecognized_keys;
json_t *value; json_t *value;
long unpacked = 0; long unpacked = 0;
if (gotopt) {
/* We have optional keys, we need to iter on each key */ if (gotopt || json_object_size(root) != key_set.size) {
json_object_foreach(root, key, value) { json_object_foreach(root, key, value) {
if(!hashtable_get(&key_set, key)) { if(!hashtable_get(&key_set, key)) {
unpacked++; unpacked++;
/* Save unrecognized keys for the error message */ /* Save unrecognized keys for the error message */
if (!have_unrecognized_keys) { if (keys_res == 1) {
strbuffer_init(&unrecognized_keys); keys_res = strbuffer_init(&unrecognized_keys);
have_unrecognized_keys = 1; } else if (!keys_res) {
} else { keys_res = strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
} }
strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
if (!keys_res)
keys_res = strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
} }
} }
} else {
/* No optional keys, we can just compare the number of items */
unpacked = (long)json_object_size(root) - (long)key_set.size;
} }
if (unpacked) { if (unpacked) {
if (!gotopt) {
/* Save unrecognized keys for the error message */
json_object_foreach(root, key, value) {
if(!hashtable_get(&key_set, key)) {
if (!have_unrecognized_keys) {
strbuffer_init(&unrecognized_keys);
have_unrecognized_keys = 1;
} else {
strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
}
strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
}
}
}
set_error(s, "<validation>", json_error_end_of_input_expected, set_error(s, "<validation>", json_error_end_of_input_expected,
"%li object item(s) left unpacked: %s", "%li object item(s) left unpacked: %s",
unpacked, strbuffer_value(&unrecognized_keys)); unpacked,
keys_res ? "<unknown>" : strbuffer_value(&unrecognized_keys));
strbuffer_close(&unrecognized_keys); strbuffer_close(&unrecognized_keys);
goto out; goto out;
} }
@ -805,6 +851,7 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags,
value = pack(&s, &ap_copy); value = pack(&s, &ap_copy);
va_end(ap_copy); va_end(ap_copy);
/* This will cover all situations where s.has_error is true */
if(!value) if(!value)
return NULL; return NULL;
@ -814,10 +861,6 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags,
set_error(&s, "<format>", json_error_invalid_format, "Garbage after format string"); set_error(&s, "<format>", json_error_invalid_format, "Garbage after format string");
return NULL; return NULL;
} }
if(s.has_error) {
json_decref(value);
return NULL;
}
return value; return value;
} }

View file

@ -13,7 +13,6 @@
#include <jansson.h> #include <jansson.h>
#include "jansson_private.h" #include "jansson_private.h"
json_t *json_path_get(const json_t *json, const char *path) json_t *json_path_get(const json_t *json, const char *path)
{ {
static const char root_chr = '$', array_open = '['; static const char root_chr = '$', array_open = '[';

View file

@ -16,7 +16,7 @@ typedef struct {
size_t size; /* bytes allocated */ size_t size; /* bytes allocated */
} strbuffer_t; } strbuffer_t;
int strbuffer_init(strbuffer_t *strbuff); int strbuffer_init(strbuffer_t *strbuff) JANSSON_ATTRS(warn_unused_result);
void strbuffer_close(strbuffer_t *strbuff); void strbuffer_close(strbuffer_t *strbuff);
void strbuffer_clear(strbuffer_t *strbuff); void strbuffer_clear(strbuffer_t *strbuff);

View file

@ -652,8 +652,7 @@ static json_t *string_create(const char *value, size_t len, int own)
string = jsonp_malloc(sizeof(json_string_t)); string = jsonp_malloc(sizeof(json_string_t));
if(!string) { if(!string) {
if(!own) jsonp_free(v);
jsonp_free(v);
return NULL; return NULL;
} }
json_init(&string->json, JSON_STRING); json_init(&string->json, JSON_STRING);
@ -768,9 +767,6 @@ static int json_string_equal(const json_t *string1, const json_t *string2)
{ {
json_string_t *s1, *s2; json_string_t *s1, *s2;
if(!json_is_string(string1) || !json_is_string(string2))
return 0;
s1 = json_to_string(string1); s1 = json_to_string(string1);
s2 = json_to_string(string2); s2 = json_to_string(string2);
return s1->length == s2->length && !memcmp(s1->value, s2->value, s1->length); return s1->length == s2->length && !memcmp(s1->value, s2->value, s1->length);
@ -780,34 +776,38 @@ static json_t *json_string_copy(const json_t *string)
{ {
json_string_t *s; json_string_t *s;
if(!json_is_string(string))
return NULL;
s = json_to_string(string); s = json_to_string(string);
return json_stringn_nocheck(s->value, s->length); return json_stringn_nocheck(s->value, s->length);
} }
json_t *json_vsprintf(const char *fmt, va_list ap) { json_t *json_vsprintf(const char *fmt, va_list ap) {
json_t *json = NULL;
int length; int length;
char *buf; char *buf;
va_list aq; va_list aq;
va_copy(aq, ap); va_copy(aq, ap);
length = vsnprintf(NULL, 0, fmt, ap); length = vsnprintf(NULL, 0, fmt, ap);
if (length == 0) if (length == 0) {
return json_string(""); json = json_string("");
goto out;
}
buf = jsonp_malloc(length + 1); buf = jsonp_malloc(length + 1);
if (!buf) if (!buf)
return NULL; goto out;
vsnprintf(buf, length + 1, fmt, aq); vsnprintf(buf, length + 1, fmt, aq);
if (!utf8_check_string(buf, length)) { if (!utf8_check_string(buf, length)) {
jsonp_free(buf); jsonp_free(buf);
return NULL; goto out;
} }
return jsonp_stringn_nocheck_own(buf, length); json = jsonp_stringn_nocheck_own(buf, length);
out:
va_end(aq);
return json;
} }
json_t *json_sprintf(const char *fmt, ...) { json_t *json_sprintf(const char *fmt, ...) {
@ -1044,8 +1044,6 @@ json_t *json_copy(json_t *json)
default: default:
return NULL; return NULL;
} }
return NULL;
} }
json_t *json_deep_copy(const json_t *json) json_t *json_deep_copy(const json_t *json)
@ -1073,6 +1071,4 @@ json_t *json_deep_copy(const json_t *json)
default: default:
return NULL; return NULL;
} }
return NULL;
} }