Extend array API

Added functions:

  json_array_insert
  json_array_insert_new
  json_array_remove
  json_array_clear
  json_array_extend
This commit is contained in:
Petri Lehtinen 2009-09-29 21:19:55 +03:00
parent b3e1fe2ec5
commit cbacac5975
5 changed files with 439 additions and 16 deletions

View File

@ -291,6 +291,44 @@ A JSON array is an ordered collection of other JSON values.
.. versionadded:: 1.1 .. versionadded:: 1.1
.. cfunction:: int json_array_insert(json_t *array, unsigned int index, json_t *value)
Inserts *value* to *array* at position *index*, shifting the
elements at *index* and after it one position towards the end of
the array. Returns 0 on success and -1 on error.
.. versionadded:: 1.1
.. cfunction:: int json_array_insert_new(json_t *array, unsigned int index, json_t *value)
Like :cfunc:`json_array_insert()` 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_remove(json_t *array, unsigned int index)
Removes the element in *array* at position *index*, shifting the
elements after *index* one position towards the start of the array.
Returns 0 on success and -1 on error.
.. versionadded:: 1.1
.. cfunction:: int json_array_clear(json_t *array)
Removes all elements from *array*. Returns 0 on sucess and -1 on
error.
.. versionadded:: 1.1
.. cfunction:: int json_array_extend(json_t *array, json_t *other_array)
Appends all elements in *other_array* to the end of *array*.
Returns 0 on success and -1 on error.
.. versionadded:: 1.1
Object Object
====== ======

View File

@ -89,6 +89,10 @@ unsigned int json_array_size(const json_t *array);
json_t *json_array_get(const json_t *array, unsigned int index); json_t *json_array_get(const json_t *array, unsigned int index);
int json_array_set_new(json_t *array, unsigned int index, 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); int json_array_append_new(json_t *array, json_t *value);
int json_array_insert_new(json_t *array, unsigned int index, json_t *value);
int json_array_remove(json_t *array, unsigned int index);
int json_array_clear(json_t *array);
int json_array_extend(json_t *array, json_t *other);
static inline static inline
int json_array_set(json_t *array, unsigned int index, json_t *value) int json_array_set(json_t *array, unsigned int index, json_t *value)
@ -102,6 +106,11 @@ int json_array_append(json_t *array, json_t *value)
return json_array_append_new(array, json_incref(value)); return json_array_append_new(array, json_incref(value));
} }
static inline
int json_array_insert(json_t *array, unsigned int index, json_t *value)
{
return json_array_insert_new(array, index, json_incref(value));
}
const char *json_string_value(const json_t *json); const char *json_string_value(const json_t *json);
int json_integer_value(const json_t *json); int json_integer_value(const json_t *json);

View File

@ -217,8 +217,13 @@ json_t *json_array(void)
json_init(&array->json, JSON_ARRAY); json_init(&array->json, JSON_ARRAY);
array->entries = 0; array->entries = 0;
array->size = 0; array->size = 8;
array->table = NULL;
array->table = malloc(array->size * sizeof(json_t *));
if(!array->table) {
free(array);
return NULL;
}
return &array->json; return &array->json;
} }
@ -281,6 +286,48 @@ int json_array_set_new(json_t *json, unsigned int index, json_t *value)
return 0; return 0;
} }
static void array_move(json_array_t *array, unsigned int dest,
unsigned int src, unsigned int count)
{
memmove(&array->table[dest], &array->table[src], count * sizeof(json_t *));
}
static void array_copy(json_t **dest, unsigned int dpos,
json_t **src, unsigned int spos,
unsigned int count)
{
memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *));
}
static json_t **json_array_grow(json_array_t *array,
unsigned int amount,
int copy)
{
unsigned int new_size;
json_t **old_table, **new_table;
if(array->entries + amount <= array->size)
return array->table;
old_table = array->table;
new_size = max(array->size + amount, array->size * 2);
new_table = malloc(new_size * sizeof(json_t *));
if(!new_table)
return NULL;
array->size = new_size;
array->table = new_table;
if(copy) {
array_copy(array->table, 0, old_table, 0, array->entries);
free(old_table);
return array->table;
}
return old_table;
}
int json_array_append_new(json_t *json, json_t *value) int json_array_append_new(json_t *json, json_t *value)
{ {
json_array_t *array; json_array_t *array;
@ -295,15 +342,10 @@ int json_array_append_new(json_t *json, json_t *value)
} }
array = json_to_array(json); array = json_to_array(json);
if(array->entries == array->size) { if(!json_array_grow(array, 1, 1)) {
array->size = max(8, array->size * 2);
array->table = realloc(array->table, array->size * sizeof(json_t *));
if(!array->table)
{
json_decref(value); json_decref(value);
return -1; return -1;
} }
}
array->table[array->entries] = value; array->table[array->entries] = value;
array->entries++; array->entries++;
@ -311,6 +353,103 @@ int json_array_append_new(json_t *json, json_t *value)
return 0; return 0;
} }
int json_array_insert_new(json_t *json, unsigned int index, json_t *value)
{
json_array_t *array;
json_t **old_table;
if(!value)
return -1;
if(!json_is_array(json)) {
json_decref(value);
return -1;
}
array = json_to_array(json);
if(index > array->entries) {
json_decref(value);
return -1;
}
old_table = json_array_grow(array, 1, 0);
if(!old_table) {
json_decref(value);
return -1;
}
if(old_table != array->table) {
array_copy(array->table, 0, old_table, 0, index);
array_copy(array->table, index + 1, old_table, index,
array->entries - index);
free(old_table);
}
else
array_move(array, index + 1, index, array->entries - index);
array->table[index] = value;
array->entries++;
return 0;
}
int json_array_remove(json_t *json, unsigned int index)
{
json_array_t *array;
if(!json_is_array(json))
return -1;
array = json_to_array(json);
if(index >= array->entries)
return -1;
json_decref(array->table[index]);
array_move(array, index, index + 1, array->entries - index);
array->entries--;
return 0;
}
int json_array_clear(json_t *json)
{
json_array_t *array;
unsigned int i;
if(!json_is_array(json))
return -1;
array = json_to_array(json);
for(i = 0; i < array->entries; i++)
json_decref(array->table[i]);
array->entries = 0;
return 0;
}
int json_array_extend(json_t *json, json_t *other_json)
{
json_array_t *array, *other;
unsigned int i;
if(!json_is_array(json) || !json_is_array(other_json))
return -1;
array = json_to_array(json);
other = json_to_array(other_json);
if(!json_array_grow(array, other->entries, 1))
return -1;
for(i = 0; i < other->entries; i++)
json_incref(other->table[i]);
array_copy(array->table, array->entries, other->table, 0, other->entries);
array->entries += other->entries;
return 0;
}
/*** string ***/ /*** string ***/

View File

@ -8,7 +8,7 @@
#include <jansson.h> #include <jansson.h>
#include "util.h" #include "util.h"
int main() static void test_misc(void)
{ {
json_t *array, *five, *seven, *value; json_t *array, *five, *seven, *value;
int i; int i;
@ -19,9 +19,7 @@ int main()
if(!array) if(!array)
fail("unable to create array"); fail("unable to create array");
if(!five) if(!five || !seven)
fail("unable to create integer");
if(!seven)
fail("unable to create integer"); fail("unable to create integer");
if(json_array_size(array) != 0) if(json_array_size(array) != 0)
@ -114,6 +112,242 @@ int main()
json_decref(five); json_decref(five);
json_decref(seven); json_decref(seven);
json_decref(array); json_decref(array);
}
static void test_insert(void)
{
json_t *array, *five, *seven, *eleven, *value;
int i;
array = json_array();
five = json_integer(5);
seven = json_integer(7);
eleven = json_integer(11);
if(!array)
fail("unable to create array");
if(!five || !seven || !eleven)
fail("unable to create integer");
if(!json_array_insert(array, 1, five))
fail("able to insert value out of bounds");
if(json_array_insert(array, 0, five))
fail("unable to insert value in an empty array");
if(json_array_get(array, 0) != five)
fail("json_array_insert works incorrectly");
if(json_array_size(array) != 1)
fail("array size is invalid after insertion");
if(json_array_insert(array, 1, seven))
fail("unable to insert value at the end of an array");
if(json_array_get(array, 0) != five)
fail("json_array_insert works incorrectly");
if(json_array_get(array, 1) != seven)
fail("json_array_insert works incorrectly");
if(json_array_size(array) != 2)
fail("array size is invalid after insertion");
if(json_array_insert(array, 1, eleven))
fail("unable to insert value in the middle of an array");
if(json_array_get(array, 0) != five)
fail("json_array_insert works incorrectly");
if(json_array_get(array, 1) != eleven)
fail("json_array_insert works incorrectly");
if(json_array_get(array, 2) != seven)
fail("json_array_insert works incorrectly");
if(json_array_size(array) != 3)
fail("array size is invalid after insertion");
if(json_array_insert_new(array, 2, json_integer(123)))
fail("unable to insert value in the middle of an array");
value = json_array_get(array, 2);
if(!json_is_integer(value) || json_integer_value(value) != 123)
fail("json_array_insert_new works incorrectly");
if(json_array_size(array) != 4)
fail("array size is invalid after insertion");
for(i = 0; i < 20; i++) {
if(json_array_insert(array, 0, seven))
fail("unable to insert value at the begining of an array");
}
for(i = 0; i < 20; i++) {
if(json_array_get(array, i) != seven)
fail("json_aray_insert works incorrectly");
}
if(json_array_size(array) != 24)
fail("array size is invalid after loop insertion");
json_decref(five);
json_decref(seven);
json_decref(eleven);
json_decref(array);
}
static void test_remove(void)
{
json_t *array, *five, *seven;
array = json_array();
five = json_integer(5);
seven = json_integer(7);
if(!array)
fail("unable to create array");
if(!five)
fail("unable to create integer");
if(!seven)
fail("unable to create integer");
if(!json_array_remove(array, 0))
fail("able to remove an unexisting index");
if(json_array_append(array, five))
fail("unable to append");
if(!json_array_remove(array, 1))
fail("able to remove an unexisting index");
if(json_array_remove(array, 0))
fail("unable to remove");
if(json_array_size(array) != 0)
fail("array size is invalid after removing");
if(json_array_append(array, five) ||
json_array_append(array, seven) ||
json_array_append(array, five) ||
json_array_append(array, seven))
fail("unable to append");
if(json_array_remove(array, 2))
fail("unable to remove");
if(json_array_size(array) != 3)
fail("array size is invalid after removing");
if(json_array_get(array, 0) != five ||
json_array_get(array, 1) != seven ||
json_array_get(array, 2) != seven)
fail("remove works incorrectly");
json_decref(five);
json_decref(seven);
json_decref(array);
}
static void test_clear(void)
{
json_t *array, *five, *seven;
int i;
array = json_array();
five = json_integer(5);
seven = json_integer(7);
if(!array)
fail("unable to create array");
if(!five || !seven)
fail("unable to create integer");
for(i = 0; i < 10; i++) {
if(json_array_append(array, five))
fail("unable to append");
}
for(i = 0; i < 10; i++) {
if(json_array_append(array, seven))
fail("unable to append");
}
if(json_array_size(array) != 20)
fail("array size is invalid after appending");
if(json_array_clear(array))
fail("unable to clear");
if(json_array_size(array) != 0)
fail("array size is invalid after clearing");
json_decref(five);
json_decref(seven);
json_decref(array);
}
static void test_extend(void)
{
json_t *array1, *array2, *five, *seven;
int i;
array1 = json_array();
array2 = json_array();
five = json_integer(5);
seven = json_integer(7);
if(!array1 || !array2)
fail("unable to create array");
if(!five || !seven)
fail("unable to create integer");
for(i = 0; i < 10; i++) {
if(json_array_append(array1, five))
fail("unable to append");
}
for(i = 0; i < 10; i++) {
if(json_array_append(array2, seven))
fail("unable to append");
}
if(json_array_size(array1) != 10 || json_array_size(array2) != 10)
fail("array size is invalid after appending");
if(json_array_extend(array1, array2))
fail("unable to extend");
for(i = 0; i < 10; i++) {
if(json_array_get(array1, i) != five)
fail("invalid array contents after extending");
}
for(i = 10; i < 20; i++) {
if(json_array_get(array1, i) != seven)
fail("invalid array contents after extending");
}
json_decref(five);
json_decref(seven);
json_decref(array1);
json_decref(array2);
}
int main()
{
test_misc();
test_insert();
test_remove();
test_clear();
test_extend();
return 0; return 0;
} }

View File

@ -8,10 +8,13 @@
#ifndef TESTPROGS_UTIL_H #ifndef TESTPROGS_UTIL_H
#define TESTPROGS_UTIL_H #define TESTPROGS_UTIL_H
#include <stdlib.h>
#define fail(msg) \ #define fail(msg) \
do { \ do { \
fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ fprintf(stderr, "%s:%s:%d: %s\n", \
return 1; \ __FILE__, __FUNCTION__, __LINE__, msg); \
exit(1); \
} while(0) } while(0)
#endif #endif