aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetri Lehtinen <petri@digip.org>2009-09-29 21:19:55 +0300
committerPetri Lehtinen <petri@digip.org>2009-09-29 22:17:58 +0300
commitcbacac597516b3d7309bf0811ea18cd43870bce4 (patch)
tree7cd4bbd0364d0377a964fe98470d32ea22788bd4
parentb3e1fe2ec5c0fb4d7307ad27fe0ac0ef14c87b37 (diff)
downloadjansson-cbacac597516b3d7309bf0811ea18cd43870bce4.zip
jansson-cbacac597516b3d7309bf0811ea18cd43870bce4.tar.gz
jansson-cbacac597516b3d7309bf0811ea18cd43870bce4.tar.bz2
Extend array API
Added functions: json_array_insert json_array_insert_new json_array_remove json_array_clear json_array_extend
-rw-r--r--doc/apiref.rst38
-rw-r--r--src/jansson.h9
-rw-r--r--src/value.c159
-rw-r--r--test/testprogs/test_array.c242
-rw-r--r--test/testprogs/util.h7
5 files changed, 439 insertions, 16 deletions
diff --git a/doc/apiref.rst b/doc/apiref.rst
index 8623623..cc6b1f1 100644
--- a/doc/apiref.rst
+++ b/doc/apiref.rst
@@ -291,6 +291,44 @@ A JSON array is an ordered collection of other JSON values.
.. 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
======
diff --git a/src/jansson.h b/src/jansson.h
index b5cdddb..b7a75b6 100644
--- a/src/jansson.h
+++ b/src/jansson.h
@@ -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);
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_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
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));
}
+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);
int json_integer_value(const json_t *json);
diff --git a/src/value.c b/src/value.c
index 29f787c..bf5fd54 100644
--- a/src/value.c
+++ b/src/value.c
@@ -217,8 +217,13 @@ json_t *json_array(void)
json_init(&array->json, JSON_ARRAY);
array->entries = 0;
- array->size = 0;
- array->table = NULL;
+ array->size = 8;
+
+ array->table = malloc(array->size * sizeof(json_t *));
+ if(!array->table) {
+ free(array);
+ return NULL;
+ }
return &array->json;
}
@@ -281,6 +286,48 @@ int json_array_set_new(json_t *json, unsigned int index, json_t *value)
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)
{
json_array_t *array;
@@ -295,14 +342,9 @@ int json_array_append_new(json_t *json, json_t *value)
}
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;
- }
+ if(!json_array_grow(array, 1, 1)) {
+ json_decref(value);
+ return -1;
}
array->table[array->entries] = value;
@@ -311,6 +353,103 @@ int json_array_append_new(json_t *json, json_t *value)
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 ***/
diff --git a/test/testprogs/test_array.c b/test/testprogs/test_array.c
index b597afb..53f6f3d 100644
--- a/test/testprogs/test_array.c
+++ b/test/testprogs/test_array.c
@@ -8,7 +8,7 @@
#include <jansson.h>
#include "util.h"
-int main()
+static void test_misc(void)
{
json_t *array, *five, *seven, *value;
int i;
@@ -19,9 +19,7 @@ int main()
if(!array)
fail("unable to create array");
- if(!five)
- fail("unable to create integer");
- if(!seven)
+ if(!five || !seven)
fail("unable to create integer");
if(json_array_size(array) != 0)
@@ -114,6 +112,242 @@ int main()
json_decref(five);
json_decref(seven);
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;
}
diff --git a/test/testprogs/util.h b/test/testprogs/util.h
index 6e518a2..ec8e0e4 100644
--- a/test/testprogs/util.h
+++ b/test/testprogs/util.h
@@ -8,10 +8,13 @@
#ifndef TESTPROGS_UTIL_H
#define TESTPROGS_UTIL_H
+#include <stdlib.h>
+
#define fail(msg) \
do { \
- fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \
- return 1; \
+ fprintf(stderr, "%s:%s:%d: %s\n", \
+ __FILE__, __FUNCTION__, __LINE__, msg); \
+ exit(1); \
} while(0)
#endif