/*
- * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
*
* Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
#include <stdlib.h>
#include <string.h>
-#include <jansson.h>
+#include "jansson.h"
#include "hashtable.h"
#include "jansson_private.h"
#include "utf.h"
/*** object ***/
-/* This macro just returns a pointer that's a few bytes backwards from
- string. This makes it possible to pass a pointer to object_key_t
- when only the string inside it is used, without actually creating
- an object_key_t instance. */
-#define string_to_key(string) container_of(string, object_key_t, key)
-
-size_t jsonp_hash_key(const void *ptr)
-{
- const char *str = ((const object_key_t *)ptr)->key;
-
- size_t hash = 5381;
- size_t c;
-
- while((c = (size_t)*str))
- {
- hash = ((hash << 5) + hash) + c;
- str++;
- }
-
- return hash;
-}
-
-int jsonp_key_equal(const void *ptr1, const void *ptr2)
-{
- return strcmp(((const object_key_t *)ptr1)->key,
- ((const object_key_t *)ptr2)->key) == 0;
-}
-
-static void value_decref(void *value)
-{
- json_decref((json_t *)value);
-}
-
json_t *json_object(void)
{
json_object_t *object = jsonp_malloc(sizeof(json_object_t));
return NULL;
json_init(&object->json, JSON_OBJECT);
- if(hashtable_init(&object->hashtable,
- jsonp_hash_key, jsonp_key_equal,
- jsonp_free, value_decref))
+ if(hashtable_init(&object->hashtable))
{
jsonp_free(object);
return NULL;
return NULL;
object = json_to_object(json);
- return hashtable_get(&object->hashtable, string_to_key(key));
+ return hashtable_get(&object->hashtable, key);
}
int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)
{
json_object_t *object;
- object_key_t *k;
- if(!key || !value)
+ if(!value)
return -1;
- if(!json_is_object(json) || json == value)
+ if(!key || !json_is_object(json) || json == value)
{
json_decref(value);
return -1;
}
object = json_to_object(json);
- /* offsetof(...) returns the size of object_key_t without the
- last, flexible member. This way, the correct amount is
- allocated. */
- k = jsonp_malloc(offsetof(object_key_t, key) + strlen(key) + 1);
- if(!k)
- return -1;
-
- k->serial = object->serial++;
- strcpy(k->key, key);
-
- if(hashtable_set(&object->hashtable, k, value))
+ if(hashtable_set(&object->hashtable, key, object->serial++, value))
{
json_decref(value);
return -1;
return -1;
object = json_to_object(json);
- return hashtable_del(&object->hashtable, string_to_key(key));
+ return hashtable_del(&object->hashtable, key);
}
int json_object_clear(json_t *json)
return -1;
object = json_to_object(json);
+
hashtable_clear(&object->hashtable);
+ object->serial = 0;
return 0;
}
int json_object_update(json_t *object, json_t *other)
{
- void *iter;
+ const char *key;
+ json_t *value;
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);
-
+ json_object_foreach(other, key, value) {
if(json_object_set_nocheck(object, key, value))
return -1;
+ }
+
+ return 0;
+}
+
+int json_object_update_existing(json_t *object, json_t *other)
+{
+ const char *key;
+ json_t *value;
- iter = json_object_iter_next(other, iter);
+ if(!json_is_object(object) || !json_is_object(other))
+ return -1;
+
+ json_object_foreach(other, key, value) {
+ if(json_object_get(object, key))
+ json_object_set_nocheck(object, key, value);
+ }
+
+ return 0;
+}
+
+int json_object_update_missing(json_t *object, json_t *other)
+{
+ const char *key;
+ json_t *value;
+
+ if(!json_is_object(object) || !json_is_object(other))
+ return -1;
+
+ json_object_foreach(other, key, value) {
+ if(!json_object_get(object, key))
+ json_object_set_nocheck(object, key, value);
}
return 0;
return NULL;
object = json_to_object(json);
- return hashtable_iter_at(&object->hashtable, string_to_key(key));
+ return hashtable_iter_at(&object->hashtable, key);
}
void *json_object_iter_next(json_t *json, void *iter)
return hashtable_iter_next(&object->hashtable, iter);
}
-const object_key_t *jsonp_object_iter_fullkey(void *iter)
-{
- if(!iter)
- return NULL;
-
- return hashtable_iter_key(iter);
-}
-
const char *json_object_iter_key(void *iter)
{
if(!iter)
return NULL;
- return jsonp_object_iter_fullkey(iter)->key;
+ return hashtable_iter_key(iter);
}
json_t *json_object_iter_value(void *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);
-
+ hashtable_iter_set(iter, value);
return 0;
}
+void *json_object_key_to_iter(const char *key)
+{
+ if(!key)
+ return NULL;
+
+ return hashtable_key_to_iter(key);
+}
+
static int json_object_equal(json_t *object1, json_t *object2)
{
- void *iter;
+ const char *key;
+ json_t *value1, *value2;
if(json_object_size(object1) != json_object_size(object2))
return 0;
- iter = json_object_iter(object1);
- while(iter)
- {
- const char *key;
- json_t *value1, *value2;
-
- key = json_object_iter_key(iter);
- value1 = json_object_iter_value(iter);
+ json_object_foreach(object1, key, value1) {
value2 = json_object_get(object2, key);
if(!json_equal(value1, value2))
return 0;
-
- iter = json_object_iter_next(object1, iter);
}
return 1;
static json_t *json_object_copy(json_t *object)
{
json_t *result;
- void *iter;
+
+ const char *key;
+ json_t *value;
result = json_object();
if(!result)
return NULL;
- iter = json_object_iter(object);
- while(iter)
- {
- const char *key;
- json_t *value;
-
- key = json_object_iter_key(iter);
- value = json_object_iter_value(iter);
+ json_object_foreach(object, key, value)
json_object_set_nocheck(result, key, value);
- iter = json_object_iter_next(object, iter);
- }
-
return result;
}
static json_t *json_object_deep_copy(json_t *object)
{
json_t *result;
- void *iter;
+
+ const char *key;
+ json_t *value;
result = json_object();
if(!result)
return NULL;
- iter = json_object_iter(object);
- while(iter)
- {
- const char *key;
- json_t *value;
-
- key = json_object_iter_key(iter);
- value = json_object_iter_value(iter);
+ json_object_foreach(object, key, value)
json_object_set_new_nocheck(result, key, json_deep_copy(value));
- iter = json_object_iter_next(object, iter);
- }
-
return result;
}
char *dup;
json_string_t *string;
+ if(!json_is_string(json) || !value)
+ return -1;
+
dup = jsonp_strdup(value);
if(!dup)
return -1;
double json_number_value(const json_t *json)
{
if(json_is_integer(json))
- return json_integer_value(json);
+ return (double)json_integer_value(json);
else if(json_is_real(json))
return json_real_value(json);
else