From 89d09813c376a1ba59a5fd015dd905e2778c7407 Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Thu, 3 Sep 2009 17:56:00 +0300 Subject: [PATCH] Add reference stealing functions for inserting values to objects and arrays The non-stealing functions are now just simple wrappers around these. --- doc/apiref.rst | 24 ++++++++++++++++++++++ src/jansson.h | 25 ++++++++++++++++++++--- src/value.c | 47 +++++++++++++++++++++++++++++++++++--------- test/testprogs/test_array.c | 10 ++++++++++ test/testprogs/test_object.c | 8 +++++++- 5 files changed, 101 insertions(+), 13 deletions(-) diff --git a/doc/apiref.rst b/doc/apiref.rst index 903b48c..c70c0bc 100644 --- a/doc/apiref.rst +++ b/doc/apiref.rst @@ -259,11 +259,27 @@ A JSON array is an ordered collection of other JSON values. range for *index* is from 0 to the return value of :cfunc:`json_array_size()` minus 1. +.. cfunction:: int json_array_set_new(json_t *array, unsigned int index, json_t *value) + + Like :cfunc:`json_array_set()` but steals the reference to *value*. + This is useful when *value* is newly created and not used after + the call. + + .. versionadded:: 1.1 + .. cfunction:: int json_array_append(json_t *array, json_t *value) Appends *value* to the end of *array*, growing the size of *array* by 1. Returns 0 on success and -1 on error. +.. cfunction:: int json_array_append_new(json_t *array, json_t *value) + + Like :cfunc:`json_array_append()` but steals the reference to + *value*. This is useful when *value* is newly created and not used + after the call. + + .. versionadded:: 1.1 + Object ====== @@ -292,6 +308,14 @@ Unicode string and the value is any JSON value. a value for *key*, it is replaced by the new value. Returns 0 on success and -1 on error. +.. cfunction:: int json_object_set_new(json_t *object, const char *key, json_t *value) + + Like :cfunc:`json_object_set()` but steals the reference to + *value*. This is useful when *value* is newly created and not used + after the call. + + .. versionadded:: 1.1 + .. cfunction:: int json_object_del(json_t *object, const char *key) Delete *key* from *object* if it exists. Returns 0 on success, or diff --git a/src/jansson.h b/src/jansson.h index 6efc6db..09af7bf 100644 --- a/src/jansson.h +++ b/src/jansson.h @@ -72,17 +72,36 @@ static inline void json_decref(json_t *json) /* getters, setters, manipulation */ json_t *json_object_get(const json_t *object, const char *key); -int json_object_set(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_del(json_t *object, const char *key); void *json_object_iter(json_t *object); void *json_object_iter_next(json_t *object, void *iter); const char *json_object_iter_key(void *iter); json_t *json_object_iter_value(void *iter); +static inline +int json_object_set(json_t *object, const char *key, json_t *value) +{ + return json_object_set_new(object, key, json_incref(value)); +} + unsigned int json_array_size(const json_t *array); json_t *json_array_get(const json_t *array, unsigned int index); -int json_array_set(json_t *array, unsigned int index, json_t *value); -int json_array_append(json_t *array, json_t *value); +int json_array_set_new(json_t *array, unsigned int index, json_t *value); +int json_array_append_new(json_t *array, json_t *value); + +static inline +int json_array_set(json_t *array, unsigned int index, json_t *value) +{ + return json_array_set_new(array, index, json_incref(value)); +} + +static inline +int json_array_append(json_t *array, json_t *value) +{ + return json_array_append_new(array, json_incref(value)); +} + const char *json_string_value(const json_t *json); int json_integer_value(const json_t *json); diff --git a/src/value.c b/src/value.c index fda0b03..d83d575 100644 --- a/src/value.c +++ b/src/value.c @@ -118,23 +118,40 @@ json_t *json_object_get(const json_t *json, const char *key) return hashtable_get(&object->hashtable, key); } -int json_object_set_nocheck(json_t *json, const char *key, json_t *value) +int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value) { json_object_t *object; if(!json_is_object(json)) + { + json_decref(value); return -1; - + } object = json_to_object(json); - return hashtable_set(&object->hashtable, strdup(key), json_incref(value)); + + if(hashtable_set(&object->hashtable, strdup(key), value)) + { + json_decref(value); + return -1; + } + + return 0; +} + +int json_object_set_nocheck(json_t *json, const char *key, json_t *value) +{ + return json_object_set_new_nocheck(json, key, json_incref(value)); } -int json_object_set(json_t *json, const char *key, json_t *value) +int json_object_set_new(json_t *json, const char *key, json_t *value) { if(!utf8_check_string(key, -1)) + { + json_decref(value); return -1; + } - return json_object_set_nocheck(json, key, value); + return json_object_set_new_nocheck(json, key, value); } int json_object_del(json_t *json, const char *key) @@ -235,37 +252,49 @@ json_t *json_array_get(const json_t *json, unsigned int index) return array->table[index]; } -int json_array_set(json_t *json, unsigned int index, json_t *value) +int json_array_set_new(json_t *json, unsigned int index, json_t *value) { json_array_t *array; if(!json_is_array(json)) + { + json_decref(value); return -1; + } array = json_to_array(json); if(index >= array->entries) + { + json_decref(value); return -1; + } json_decref(array->table[index]); - array->table[index] = json_incref(value); + array->table[index] = value; return 0; } -int json_array_append(json_t *json, json_t *value) +int json_array_append_new(json_t *json, json_t *value) { json_array_t *array; if(!json_is_array(json)) + { + json_decref(value); return -1; + } array = json_to_array(json); if(array->entries == array->size) { array->size = max(8, array->size * 2); array->table = realloc(array->table, array->size * sizeof(json_t *)); if(!array->table) + { + json_decref(value); return -1; + } } - array->table[array->entries] = json_incref(value); + array->table[array->entries] = value; array->entries++; return 0; diff --git a/test/testprogs/test_array.c b/test/testprogs/test_array.c index 0ebc3d5..97a8513 100644 --- a/test/testprogs/test_array.c +++ b/test/testprogs/test_array.c @@ -85,6 +85,16 @@ int main() fail("got wrong value"); } + json_array_set_new(array, 15, json_integer(123)); + value = json_array_get(array, 15); + if(!json_is_integer(value) || json_integer_value(value) != 123) + fail("json_array_set_new works incorrectly"); + + json_array_append_new(array, json_integer(321)); + value = json_array_get(array, json_array_size(array) - 1); + if(!json_is_integer(value) || json_integer_value(value) != 321) + fail("json_array_append_new works incorrectly"); + json_decref(five); json_decref(seven); json_decref(array); diff --git a/test/testprogs/test_object.c b/test/testprogs/test_object.c index 9f72374..1b42c02 100644 --- a/test/testprogs/test_object.c +++ b/test/testprogs/test_object.c @@ -73,7 +73,7 @@ int main() fail("unable to delete an existing key"); - /* add many keys to rehashing */ + /* add many keys to initiate rehashing */ if(json_object_set(object, "a", string)) fail("unable to set value"); @@ -93,6 +93,12 @@ int main() if(json_object_set(object, "e", string)) fail("unable to set value"); + + json_object_set_new(object, "foo", json_integer(123)); + value = json_object_get(object, "foo"); + if(!json_is_integer(value) || json_integer_value(value) != 123) + fail("json_object_set_new works incorrectly"); + json_decref(string); json_decref(other_string); json_decref(object); -- 2.7.4