+/*
+ * Copyright (c) 2009 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.
+ */
+
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <jansson.h>
#include "hashtable.h"
-
-#define max(a, b) ((a) > (b) ? (a) : (b))
+#include "jansson_private.h"
+#include "utf.h"
+#include "util.h"
#define container_of(ptr_, type_, member_) \
((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_))
typedef struct {
json_t json;
- hashtable_t *hashtable;
+ hashtable_t hashtable;
} json_object_t;
typedef struct {
typedef struct {
json_t json;
double value;
-} json_number_t;
+} json_real_t;
+
+typedef struct {
+ json_t json;
+ int value;
+} json_integer_t;
#define json_to_object(json_) container_of(json_, json_object_t, json)
#define json_to_array(json_) container_of(json_, json_array_t, json)
#define json_to_string(json_) container_of(json_, json_string_t, json)
-#define json_to_number(json_) container_of(json_, json_number_t, json)
+#define json_to_real(json_) container_of(json_, json_real_t, json)
+#define json_to_integer(json_) container_of(json_, json_integer_t, json)
static inline void json_init(json_t *json, json_type type)
{
return NULL;
json_init(&object->json, JSON_OBJECT);
- object->hashtable =
- hashtable_new(hash_string, string_equal, free, value_decref);
- if(!object->hashtable)
+ if(hashtable_init(&object->hashtable, hash_string, string_equal,
+ free, value_decref))
{
free(object);
return NULL;
static void json_delete_object(json_object_t *object)
{
- hashtable_free(object->hashtable);
+ hashtable_close(&object->hashtable);
free(object);
}
if(!json_is_object(json))
return NULL;
- return hashtable_get(object->hashtable, key);
+ object = json_to_object(json);
+ return hashtable_get(&object->hashtable, key);
}
-int json_object_set(json_t *json, const char *key, json_t *value)
+int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)
{
json_object_t *object;
- if(!json_is_object(json))
+ if(!key || !value)
return -1;
+ if(!json_is_object(json))
+ {
+ json_decref(value);
+ return -1;
+ }
object = json_to_object(json);
- return hashtable_set(object->hashtable, strdup(key), json_incref(value));
+
+ if(hashtable_set(&object->hashtable, strdup(key), value))
+ {
+ json_decref(value);
+ return -1;
+ }
+
+ return 0;
+}
+
+int json_object_set_nocheck(json_t *json, const char *key, json_t *value)
+{
+ return json_object_set_new_nocheck(json, key, json_incref(value));
+}
+
+int json_object_set_new(json_t *json, const char *key, json_t *value)
+{
+ if(!utf8_check_string(key, -1))
+ {
+ json_decref(value);
+ return -1;
+ }
+
+ return json_object_set_new_nocheck(json, key, value);
}
int json_object_del(json_t *json, const char *key)
return -1;
object = json_to_object(json);
- return hashtable_del(object->hashtable, key);
+ return hashtable_del(&object->hashtable, key);
}
void *json_object_iter(json_t *json)
return NULL;
object = json_to_object(json);
- return hashtable_iter(object->hashtable);
+ return hashtable_iter(&object->hashtable);
}
void *json_object_iter_next(json_t *json, void *iter)
return NULL;
object = json_to_object(json);
- return hashtable_iter_next(object->hashtable, iter);
+ return hashtable_iter_next(&object->hashtable, iter);
}
const char *json_object_iter_key(void *iter)
return NULL;
array = json_to_array(json);
- if(index >= array->size)
+ if(index >= array->entries)
return NULL;
return array->table[index];
}
-int json_array_set(json_t *json, unsigned int index, json_t *value)
+int json_array_set_new(json_t *json, unsigned int index, json_t *value)
{
json_array_t *array;
+
+ if(!value)
+ return -1;
+
if(!json_is_array(json))
+ {
+ json_decref(value);
return -1;
+ }
array = json_to_array(json);
- if(index >= array->size)
+ if(index >= array->entries)
+ {
+ json_decref(value);
return -1;
+ }
+
+ json_decref(array->table[index]);
+ array->table[index] = value;
- array->table[index] = json_incref(value);
return 0;
}
-int json_array_append(json_t *json, json_t *value)
+int json_array_append_new(json_t *json, json_t *value)
{
json_array_t *array;
+
+ if(!value)
+ return -1;
+
if(!json_is_array(json))
+ {
+ json_decref(value);
return -1;
+ }
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;
+ }
}
- array->table[array->entries] = json_incref(value);
+ array->table[array->entries] = value;
array->entries++;
return 0;
/*** string ***/
-json_t *json_string(const char *value)
+json_t *json_string_nocheck(const char *value)
{
- json_string_t *string = malloc(sizeof(json_string_t));
+ json_string_t *string;
+
+ if(!value)
+ return NULL;
+
+ string = malloc(sizeof(json_string_t));
if(!string)
return NULL;
json_init(&string->json, JSON_STRING);
string->value = strdup(value);
+ if(!string->value) {
+ free(string);
+ return NULL;
+ }
+
return &string->json;
}
+json_t *json_string(const char *value)
+{
+ if(!value || !utf8_check_string(value, -1))
+ return NULL;
+
+ return json_string_nocheck(value);
+}
+
const char *json_string_value(const json_t *json)
{
if(!json_is_string(json))
free(string);
}
-json_t *json_number(double value)
+
+/*** integer ***/
+
+json_t *json_integer(int value)
{
- json_number_t *number = malloc(sizeof(json_number_t));
- if(!number)
+ json_integer_t *integer = malloc(sizeof(json_integer_t));
+ if(!integer)
return NULL;
- json_init(&number->json, JSON_NUMBER);
+ json_init(&integer->json, JSON_INTEGER);
- number->value = value;
- return &number->json;
+ integer->value = value;
+ return &integer->json;
}
+int json_integer_value(const json_t *json)
+{
+ if(!json_is_integer(json))
+ return 0;
-/*** number ***/
+ return json_to_integer(json)->value;
+}
-double json_number_value(const json_t *json)
+static void json_delete_integer(json_integer_t *integer)
{
- if(!json_is_number(json))
- return 0.0;
+ free(integer);
+}
+
+
+/*** real ***/
+
+json_t *json_real(double value)
+{
+ json_real_t *real = malloc(sizeof(json_real_t));
+ if(!real)
+ return NULL;
+ json_init(&real->json, JSON_REAL);
+
+ real->value = value;
+ return &real->json;
+}
+
+double json_real_value(const json_t *json)
+{
+ if(!json_is_real(json))
+ return 0;
- return json_to_number(json)->value;
+ return json_to_real(json)->value;
}
-static void json_delete_number(json_number_t *number)
+static void json_delete_real (json_real_t *real)
+{
+ free(real);
+}
+
+
+/*** number ***/
+
+double json_number_value(const json_t *json)
{
- free(number);
+ if(json_is_integer(json))
+ return json_integer_value(json);
+ else if(json_is_real(json))
+ return json_real_value(json);
+ else
+ return 0.0;
}
else if(json_is_string(json))
json_delete_string(json_to_string(json));
- else if(json_is_number(json))
- json_delete_number(json_to_number(json));
+ else if(json_is_integer(json))
+ json_delete_integer(json_to_integer(json));
+
+ else if(json_is_real(json))
+ json_delete_real(json_to_real(json));
/* json_delete is not called for true, false or null */
}