Extend object API
Added functions: json_object_size json_object_clear json_object_update
This commit is contained in:
parent
40bb7bf437
commit
1e00cd58a5
@ -343,6 +343,13 @@ Unicode string and the value is any JSON value.
|
|||||||
Returns a new JSON object, or *NULL* on error. Initially, the
|
Returns a new JSON object, or *NULL* on error. Initially, the
|
||||||
object is empty.
|
object is empty.
|
||||||
|
|
||||||
|
.. cfunction:: unsigned int json_object_size(const json_t *object)
|
||||||
|
|
||||||
|
Returns the number of elements in *object*, or 0 if *object* is not
|
||||||
|
a JSON object.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1
|
||||||
|
|
||||||
.. cfunction:: json_t *json_object_get(const json_t *object, const char *key)
|
.. cfunction:: json_t *json_object_get(const json_t *object, const char *key)
|
||||||
|
|
||||||
.. refcounting:: borrow
|
.. refcounting:: borrow
|
||||||
@ -371,6 +378,21 @@ Unicode string and the value is any JSON value.
|
|||||||
-1 if *key* was not found.
|
-1 if *key* was not found.
|
||||||
|
|
||||||
|
|
||||||
|
.. cfunction:: int json_object_clear(json_t *object)
|
||||||
|
|
||||||
|
Remove all elements from *object*. Returns 0 on success and -1 if
|
||||||
|
*object* is not a JSON object.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1
|
||||||
|
|
||||||
|
.. cfunction:: int json_object_update(json_t *object, json_t *other)
|
||||||
|
|
||||||
|
Update *object* with the key-value pairs from *other*, overwriting
|
||||||
|
existing keys. Returns 0 on success or -1 on error.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1
|
||||||
|
|
||||||
|
|
||||||
The following functions implement an iteration protocol for objects:
|
The following functions implement an iteration protocol for objects:
|
||||||
|
|
||||||
.. cfunction:: void *json_object_iter(json_t *object)
|
.. cfunction:: void *json_object_iter(json_t *object)
|
||||||
|
@ -133,6 +133,23 @@ static int hashtable_do_del(hashtable_t *hashtable,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hashtable_do_clear(hashtable_t *hashtable)
|
||||||
|
{
|
||||||
|
list_t *list, *next;
|
||||||
|
pair_t *pair;
|
||||||
|
|
||||||
|
for(list = hashtable->list.next; list != &hashtable->list; list = next)
|
||||||
|
{
|
||||||
|
next = list->next;
|
||||||
|
pair = list_to_pair(list);
|
||||||
|
if(hashtable->free_key)
|
||||||
|
hashtable->free_key(pair->key);
|
||||||
|
if(hashtable->free_value)
|
||||||
|
hashtable->free_value(pair->value);
|
||||||
|
free(pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int hashtable_do_rehash(hashtable_t *hashtable)
|
static int hashtable_do_rehash(hashtable_t *hashtable)
|
||||||
{
|
{
|
||||||
list_t *list, *next;
|
list_t *list, *next;
|
||||||
@ -220,19 +237,7 @@ int hashtable_init(hashtable_t *hashtable,
|
|||||||
|
|
||||||
void hashtable_close(hashtable_t *hashtable)
|
void hashtable_close(hashtable_t *hashtable)
|
||||||
{
|
{
|
||||||
list_t *list, *next;
|
hashtable_do_clear(hashtable);
|
||||||
pair_t *pair;
|
|
||||||
for(list = hashtable->list.next; list != &hashtable->list; list = next)
|
|
||||||
{
|
|
||||||
next = list->next;
|
|
||||||
pair = list_to_pair(list);
|
|
||||||
if(hashtable->free_key)
|
|
||||||
hashtable->free_key(pair->key);
|
|
||||||
if(hashtable->free_value)
|
|
||||||
hashtable->free_value(pair->value);
|
|
||||||
free(pair);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(hashtable->buckets);
|
free(hashtable->buckets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,6 +297,22 @@ int hashtable_del(hashtable_t *hashtable, const void *key)
|
|||||||
return hashtable_do_del(hashtable, key, hash);
|
return hashtable_do_del(hashtable, key, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hashtable_clear(hashtable_t *hashtable)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
hashtable_do_clear(hashtable);
|
||||||
|
|
||||||
|
for(i = 0; i < num_buckets(hashtable); i++)
|
||||||
|
{
|
||||||
|
hashtable->buckets[i].first = hashtable->buckets[i].last =
|
||||||
|
&hashtable->list;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_init(&hashtable->list);
|
||||||
|
hashtable->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void *hashtable_iter(hashtable_t *hashtable)
|
void *hashtable_iter(hashtable_t *hashtable)
|
||||||
{
|
{
|
||||||
return hashtable_iter_next(hashtable, &hashtable->list);
|
return hashtable_iter_next(hashtable, &hashtable->list);
|
||||||
|
@ -134,6 +134,15 @@ void *hashtable_get(hashtable_t *hashtable, const void *key);
|
|||||||
*/
|
*/
|
||||||
int hashtable_del(hashtable_t *hashtable, const void *key);
|
int hashtable_del(hashtable_t *hashtable, const void *key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_clear - Clear hashtable
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
*
|
||||||
|
* Removes all items from the hashtable.
|
||||||
|
*/
|
||||||
|
void hashtable_clear(hashtable_t *hashtable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hashtable_iter - Iterate over hashtable
|
* hashtable_iter - Iterate over hashtable
|
||||||
*
|
*
|
||||||
|
@ -71,9 +71,12 @@ static inline void json_decref(json_t *json)
|
|||||||
|
|
||||||
/* getters, setters, manipulation */
|
/* getters, setters, manipulation */
|
||||||
|
|
||||||
|
unsigned int 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);
|
||||||
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_del(json_t *object, const char *key);
|
int json_object_del(json_t *object, const char *key);
|
||||||
|
int json_object_clear(json_t *object);
|
||||||
|
int json_object_update(json_t *object, json_t *other);
|
||||||
void *json_object_iter(json_t *object);
|
void *json_object_iter(json_t *object);
|
||||||
void *json_object_iter_next(json_t *object, void *iter);
|
void *json_object_iter_next(json_t *object, void *iter);
|
||||||
const char *json_object_iter_key(void *iter);
|
const char *json_object_iter_key(void *iter);
|
||||||
|
48
src/value.c
48
src/value.c
@ -107,6 +107,17 @@ static void json_delete_object(json_object_t *object)
|
|||||||
free(object);
|
free(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int json_object_size(const json_t *json)
|
||||||
|
{
|
||||||
|
json_object_t *object;
|
||||||
|
|
||||||
|
if(!json_is_object(json))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
object = json_to_object(json);
|
||||||
|
return object->hashtable.size;
|
||||||
|
}
|
||||||
|
|
||||||
json_t *json_object_get(const json_t *json, const char *key)
|
json_t *json_object_get(const json_t *json, const char *key)
|
||||||
{
|
{
|
||||||
json_object_t *object;
|
json_object_t *object;
|
||||||
@ -168,6 +179,43 @@ int json_object_del(json_t *json, const char *key)
|
|||||||
return hashtable_del(&object->hashtable, key);
|
return hashtable_del(&object->hashtable, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int json_object_clear(json_t *json)
|
||||||
|
{
|
||||||
|
json_object_t *object;
|
||||||
|
|
||||||
|
if(!json_is_object(json))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
object = json_to_object(json);
|
||||||
|
hashtable_clear(&object->hashtable);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int json_object_update(json_t *object, json_t *other)
|
||||||
|
{
|
||||||
|
void *iter;
|
||||||
|
|
||||||
|
if(!json_is_object(object) || !json_is_object(other))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
iter = json_object_iter(other);
|
||||||
|
while(iter) {
|
||||||
|
const char *key;
|
||||||
|
json_t *value;
|
||||||
|
|
||||||
|
key = json_object_iter_key(iter);
|
||||||
|
value = json_object_iter_value(iter);
|
||||||
|
|
||||||
|
if(json_object_set(object, key, value))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
iter = json_object_iter_next(other, iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void *json_object_iter(json_t *json)
|
void *json_object_iter(json_t *json)
|
||||||
{
|
{
|
||||||
json_object_t *object;
|
json_object_t *object;
|
||||||
|
@ -9,7 +9,137 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
int main()
|
static void test_clear()
|
||||||
|
{
|
||||||
|
json_t *object, *ten;
|
||||||
|
|
||||||
|
object = json_object();
|
||||||
|
ten = json_integer(10);
|
||||||
|
|
||||||
|
if(!object)
|
||||||
|
fail("unable to create object");
|
||||||
|
if(!ten)
|
||||||
|
fail("unable to create integer");
|
||||||
|
|
||||||
|
if(json_object_set(object, "a", ten) ||
|
||||||
|
json_object_set(object, "b", ten) ||
|
||||||
|
json_object_set(object, "c", ten) ||
|
||||||
|
json_object_set(object, "d", ten) ||
|
||||||
|
json_object_set(object, "e", ten))
|
||||||
|
fail("unable to set value");
|
||||||
|
|
||||||
|
if(json_object_size(object) != 5)
|
||||||
|
fail("invalid size");
|
||||||
|
|
||||||
|
json_object_clear(object);
|
||||||
|
|
||||||
|
if(json_object_size(object) != 0)
|
||||||
|
fail("invalid size after clear");
|
||||||
|
|
||||||
|
json_decref(ten);
|
||||||
|
json_decref(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_update()
|
||||||
|
{
|
||||||
|
json_t *object, *other, *nine, *ten;
|
||||||
|
|
||||||
|
object = json_object();
|
||||||
|
other = json_object();
|
||||||
|
|
||||||
|
nine = json_integer(9);
|
||||||
|
ten = json_integer(10);
|
||||||
|
|
||||||
|
if(!object || !other)
|
||||||
|
fail("unable to create object");
|
||||||
|
if(!nine || !ten)
|
||||||
|
fail("unable to create integer");
|
||||||
|
|
||||||
|
|
||||||
|
/* update an empty object with an empty object */
|
||||||
|
|
||||||
|
if(json_object_update(object, other))
|
||||||
|
fail("unable to update an emtpy object with an empty object");
|
||||||
|
|
||||||
|
if(json_object_size(object) != 0)
|
||||||
|
fail("invalid size after update");
|
||||||
|
|
||||||
|
if(json_object_size(other) != 0)
|
||||||
|
fail("invalid size for updater after update");
|
||||||
|
|
||||||
|
|
||||||
|
/* update an empty object with a nonempty object */
|
||||||
|
|
||||||
|
if(json_object_set(other, "a", ten) ||
|
||||||
|
json_object_set(other, "b", ten) ||
|
||||||
|
json_object_set(other, "c", ten) ||
|
||||||
|
json_object_set(other, "d", ten) ||
|
||||||
|
json_object_set(other, "e", ten))
|
||||||
|
fail("unable to set value");
|
||||||
|
|
||||||
|
if(json_object_update(object, other))
|
||||||
|
fail("unable to update an empty object");
|
||||||
|
|
||||||
|
if(json_object_size(object) != 5)
|
||||||
|
fail("invalid size after update");
|
||||||
|
|
||||||
|
if(json_object_get(object, "a") != ten ||
|
||||||
|
json_object_get(object, "b") != ten ||
|
||||||
|
json_object_get(object, "c") != ten ||
|
||||||
|
json_object_get(object, "d") != ten ||
|
||||||
|
json_object_get(object, "e") != ten)
|
||||||
|
fail("update works incorrectly");
|
||||||
|
|
||||||
|
|
||||||
|
/* perform the same update again */
|
||||||
|
|
||||||
|
if(json_object_update(object, other))
|
||||||
|
fail("unable to update an empty object");
|
||||||
|
|
||||||
|
if(json_object_size(object) != 5)
|
||||||
|
fail("invalid size after update");
|
||||||
|
|
||||||
|
if(json_object_get(object, "a") != ten ||
|
||||||
|
json_object_get(object, "b") != ten ||
|
||||||
|
json_object_get(object, "c") != ten ||
|
||||||
|
json_object_get(object, "d") != ten ||
|
||||||
|
json_object_get(object, "e") != ten)
|
||||||
|
fail("update works incorrectly");
|
||||||
|
|
||||||
|
|
||||||
|
/* update a nonempty object with a nonempty object with both old
|
||||||
|
and new keys */
|
||||||
|
|
||||||
|
if(json_object_clear(other))
|
||||||
|
fail("clear failed");
|
||||||
|
|
||||||
|
if(json_object_set(other, "a", nine) ||
|
||||||
|
json_object_set(other, "b", nine) ||
|
||||||
|
json_object_set(other, "f", nine) ||
|
||||||
|
json_object_set(other, "g", nine) ||
|
||||||
|
json_object_set(other, "h", nine))
|
||||||
|
fail("unable to set value");
|
||||||
|
|
||||||
|
if(json_object_update(object, other))
|
||||||
|
fail("unable to update a nonempty object");
|
||||||
|
|
||||||
|
if(json_object_size(object) != 8)
|
||||||
|
fail("invalid size after update");
|
||||||
|
|
||||||
|
if(json_object_get(object, "a") != nine ||
|
||||||
|
json_object_get(object, "b") != nine ||
|
||||||
|
json_object_get(object, "f") != nine ||
|
||||||
|
json_object_get(object, "g") != nine ||
|
||||||
|
json_object_get(object, "h") != nine)
|
||||||
|
fail("update works incorrectly");
|
||||||
|
|
||||||
|
json_decref(nine);
|
||||||
|
json_decref(ten);
|
||||||
|
json_decref(other);
|
||||||
|
json_decref(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_misc()
|
||||||
{
|
{
|
||||||
json_t *object, *string, *other_string, *value;
|
json_t *object, *string, *other_string, *value;
|
||||||
void *iter;
|
void *iter;
|
||||||
@ -20,9 +150,7 @@ int main()
|
|||||||
|
|
||||||
if(!object)
|
if(!object)
|
||||||
fail("unable to create object");
|
fail("unable to create object");
|
||||||
if(!string)
|
if(!string || !other_string)
|
||||||
fail("unable to create string");
|
|
||||||
if(!other_string)
|
|
||||||
fail("unable to create string");
|
fail("unable to create string");
|
||||||
|
|
||||||
if(json_object_get(object, "a"))
|
if(json_object_get(object, "a"))
|
||||||
@ -129,6 +257,13 @@ int main()
|
|||||||
json_decref(string);
|
json_decref(string);
|
||||||
json_decref(other_string);
|
json_decref(other_string);
|
||||||
json_decref(object);
|
json_decref(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_misc();
|
||||||
|
test_clear();
|
||||||
|
test_update();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user