Add functions json_object_iter_{at,set,set_new}
authorPetri Lehtinen <petri@digip.org>
Mon, 1 Feb 2010 19:01:24 +0000 (21:01 +0200)
committerPetri Lehtinen <petri@digip.org>
Mon, 1 Feb 2010 19:07:19 +0000 (21:07 +0200)
doc/apiref.rst
src/hashtable.c
src/hashtable.h
src/jansson.h
src/value.c
test/suites/api/check-exports
test/suites/api/test_object.c

index a2a0794..0a96999 100644 (file)
@@ -493,6 +493,16 @@ The following functions implement an iteration protocol for objects:
    Returns an opaque iterator which can be used to iterate over all
    key-value pairs in *object*, or *NULL* if *object* is empty.
 
    Returns an opaque iterator which can be used to iterate over all
    key-value pairs in *object*, or *NULL* if *object* is empty.
 
+.. cfunction:: void *json_object_iter_at(json_t *object, const char *key)
+
+   Like :cfunc:`json_object_iter()`, but returns an iterator to the
+   key-value pair in *object* whose key is equal to *key*, or NULL if
+   *key* is not found in *object*. Iterating forward to the end of
+   *object* only yields all key-value pairs of the object if *key*
+   happens to be the first key in the underlying hash table.
+
+   .. versionadded:: 1.3
+
 .. cfunction:: void *json_object_iter_next(json_t *object, void *iter)
 
    Returns an iterator pointing to the next key-value pair in *object*
 .. cfunction:: void *json_object_iter_next(json_t *object, void *iter)
 
    Returns an iterator pointing to the next key-value pair in *object*
@@ -509,6 +519,21 @@ The following functions implement an iteration protocol for objects:
 
    Extract the associated value from *iter*.
 
 
    Extract the associated value from *iter*.
 
+.. cfunction:: int json_object_iter_set(json_t *object, void *iter, json_t *value)
+
+   Set the value of the key-value pair in *object*, that is pointed to
+   by *iter*, to *value*.
+
+   .. versionadded:: 1.3
+
+.. cfunction:: int json_object_iter_set_new(json_t *object, void *iter, json_t *value)
+
+   Like :cfunc:`json_object_iter_set()`, but steals the reference to
+   *value*. This is useful when *value* is newly created and not used
+   after the call.
+
+   .. versionadded:: 1.3
+
 The iteration protocol can be used for example as follows::
 
    /* obj is a JSON object */
 The iteration protocol can be used for example as follows::
 
    /* obj is a JSON object */
index 05dc167..990fd6e 100644 (file)
@@ -318,6 +318,22 @@ void *hashtable_iter(hashtable_t *hashtable)
     return hashtable_iter_next(hashtable, &hashtable->list);
 }
 
     return hashtable_iter_next(hashtable, &hashtable->list);
 }
 
+void *hashtable_iter_at(hashtable_t *hashtable, const void *key)
+{
+    pair_t *pair;
+    unsigned int hash;
+    bucket_t *bucket;
+
+    hash = hashtable->hash_key(key);
+    bucket = &hashtable->buckets[hash % num_buckets(hashtable)];
+
+    pair = hashtable_find_pair(hashtable, bucket, key, hash);
+    if(!pair)
+        return NULL;
+
+    return &pair->list;
+}
+
 void *hashtable_iter_next(hashtable_t *hashtable, void *iter)
 {
     list_t *list = (list_t *)iter;
 void *hashtable_iter_next(hashtable_t *hashtable, void *iter)
 {
     list_t *list = (list_t *)iter;
@@ -337,3 +353,13 @@ void *hashtable_iter_value(void *iter)
     pair_t *pair = list_to_pair((list_t *)iter);
     return pair->value;
 }
     pair_t *pair = list_to_pair((list_t *)iter);
     return pair->value;
 }
+
+void hashtable_iter_set(hashtable_t *hashtable, void *iter, void *value)
+{
+    pair_t *pair = list_to_pair((list_t *)iter);
+
+    if(hashtable->free_value)
+        hashtable->free_value(pair->value);
+
+    pair->value = value;
+}
index 81a0af5..e920c6b 100644 (file)
@@ -161,6 +161,17 @@ void hashtable_clear(hashtable_t *hashtable);
 void *hashtable_iter(hashtable_t *hashtable);
 
 /**
 void *hashtable_iter(hashtable_t *hashtable);
 
 /**
+ * hashtable_iter - Return an iterator at a specific key
+ *
+ * @hashtable: The hashtable object
+ * @key: The key that the iterator should point to
+ *
+ * Like hashtable_iter() but returns an iterator pointing to a
+ * specific key.
+ */
+void *hashtable_iter_at(hashtable_t *hashtable, const void *key);
+
+/**
  * hashtable_iter_next - Advance an iterator
  *
  * @hashtable: The hashtable object
  * hashtable_iter_next - Advance an iterator
  *
  * @hashtable: The hashtable object
@@ -185,4 +196,12 @@ void *hashtable_iter_key(void *iter);
  */
 void *hashtable_iter_value(void *iter);
 
  */
 void *hashtable_iter_value(void *iter);
 
+/**
+ * hashtable_iter_set - Set the value pointed by an iterator
+ *
+ * @iter: The iterator
+ * @value: The value to set
+ */
+void hashtable_iter_set(hashtable_t *hashtable, void *iter, void *value);
+
 #endif
 #endif
index 73f6ce0..d703c7b 100644 (file)
@@ -83,9 +83,11 @@ 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);
 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_at(json_t *object, const char *key);
 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);
 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);
+int json_object_iter_set_new(json_t *object, void *iter, json_t *value);
 
 static inline
 int json_object_set(json_t *object, const char *key, json_t *value)
 
 static inline
 int json_object_set(json_t *object, const char *key, json_t *value)
@@ -99,6 +101,12 @@ int json_object_set_nocheck(json_t *object, const char *key, json_t *value)
     return json_object_set_new_nocheck(object, key, json_incref(value));
 }
 
     return json_object_set_new_nocheck(object, key, json_incref(value));
 }
 
+static inline
+int json_object_iter_set(json_t *object, void *iter, json_t *value)
+{
+    return json_object_iter_set_new(object, iter, 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_new(json_t *array, unsigned int index, json_t *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_new(json_t *array, unsigned int index, json_t *value);
index 01e180e..31109ff 100644 (file)
@@ -190,6 +190,17 @@ void *json_object_iter(json_t *json)
     return hashtable_iter(&object->hashtable);
 }
 
     return hashtable_iter(&object->hashtable);
 }
 
+void *json_object_iter_at(json_t *json, const char *key)
+{
+    json_object_t *object;
+
+    if(!key || !json_is_object(json))
+        return NULL;
+
+    object = json_to_object(json);
+    return hashtable_iter_at(&object->hashtable, key);
+}
+
 void *json_object_iter_next(json_t *json, void *iter)
 {
     json_object_t *object;
 void *json_object_iter_next(json_t *json, void *iter)
 {
     json_object_t *object;
@@ -217,6 +228,19 @@ json_t *json_object_iter_value(void *iter)
     return (json_t *)hashtable_iter_value(iter);
 }
 
     return (json_t *)hashtable_iter_value(iter);
 }
 
+int json_object_iter_set_new(json_t *json, void *iter, json_t *value)
+{
+    json_object_t *object;
+
+    if(!json_is_object(json) || !iter || !value)
+        return -1;
+
+    object = json_to_object(json);
+    hashtable_iter_set(&object->hashtable, iter, value);
+
+    return 0;
+}
+
 static int json_object_equal(json_t *object1, json_t *object2)
 {
     void *iter;
 static int json_object_equal(json_t *object1, json_t *object2)
 {
     void *iter;
index 178abeb..a6d877f 100755 (executable)
@@ -39,9 +39,11 @@ json_object_del
 json_object_clear
 json_object_update
 json_object_iter
 json_object_clear
 json_object_update
 json_object_iter
+json_object_iter_at
 json_object_iter_next
 json_object_iter_key
 json_object_iter_value
 json_object_iter_next
 json_object_iter_key
 json_object_iter_value
+json_object_iter_set_new
 json_dumps
 json_dumpf
 json_dump_file
 json_dumps
 json_dumpf
 json_dump_file
index 849dac0..99d0a56 100644 (file)
@@ -258,6 +258,36 @@ static void test_iterators()
     if(json_object_iter_next(object, iter) != NULL)
         fail("able to iterate over the end");
 
     if(json_object_iter_next(object, iter) != NULL)
         fail("able to iterate over the end");
 
+    if(json_object_iter_at(object, "foo"))
+        fail("json_object_iter_at() succeeds for non-existent key");
+
+    iter = json_object_iter_at(object, "b");
+    if(!iter)
+        fail("json_object_iter_at() fails for an existing key");
+
+    if(strcmp(json_object_iter_key(iter), "b"))
+        fail("iterating failed: wrong key");
+    if(json_object_iter_value(iter) != bar)
+        fail("iterating failed: wrong value");
+
+    iter = json_object_iter_next(object, iter);
+    if(!iter)
+        fail("unable to increment iterator");
+    if(strcmp(json_object_iter_key(iter), "c"))
+        fail("iterating failed: wrong key");
+    if(json_object_iter_value(iter) != baz)
+        fail("iterating failed: wrong value");
+
+    if(json_object_iter_set(object, iter, bar))
+        fail("unable to set value at iterator");
+
+    if(strcmp(json_object_iter_key(iter), "c"))
+        fail("json_object_iter_key() fails after json_object_iter_set()");
+    if(json_object_iter_value(iter) != bar)
+        fail("json_object_iter_value() fails after json_object_iter_set()");
+    if(json_object_get(object, "c") != bar)
+        fail("json_object_get() fails after json_object_iter_set()");
+
     json_decref(object);
     json_decref(foo);
     json_decref(bar);
     json_decref(object);
     json_decref(foo);
     json_decref(bar);