diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-09-07 20:11:48 +0400 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-09-07 20:11:48 +0400 |
commit | 9af09b7467a4b9b7b2c9fbf1390b481e71bb07c6 (patch) | |
tree | 79c72ede24341ad6f47b63df0521ba3ff6591d65 /src/json/value.c | |
parent | d1b63d4cff12936a5ea4380bccadcc77b7c3ed3f (diff) | |
download | rspamd-9af09b7467a4b9b7b2c9fbf1390b481e71bb07c6.tar.gz rspamd-9af09b7467a4b9b7b2c9fbf1390b481e71bb07c6.zip |
* Add JSON settings parser
Diffstat (limited to 'src/json/value.c')
-rw-r--r-- | src/json/value.c | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/src/json/value.c b/src/json/value.c new file mode 100644 index 000000000..9270f1f76 --- /dev/null +++ b/src/json/value.c @@ -0,0 +1,504 @@ +/* + * 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. + */ + + +#include "jansson.h" +#include "hashtable.h" +#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; +} json_object_t; + +typedef struct { + json_t json; + unsigned int size; + unsigned int entries; + json_t **table; +} json_array_t; + +typedef struct { + json_t json; + char *value; +} json_string_t; + +typedef struct { + json_t json; + double value; +} 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_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) +{ + json->type = type; + json->refcount = 1; +} + + +/*** object ***/ + +static unsigned int +hash_string (const void *key) +{ + const char *str = (const char *)key; + unsigned int hash = 5381; + unsigned int c; + + while ((c = (unsigned int)*str)) { + hash = ((hash << 5) + hash) + c; + str++; + } + + return hash; +} + +static int +string_equal (const void *key1, const void *key2) +{ + return strcmp ((const char *)key1, (const char *)key2) == 0; +} + +static void +value_decref (void *value) +{ + json_decref ((json_t *) value); +} + +json_t * +json_object (void) +{ + json_object_t *object = g_malloc (sizeof (json_object_t)); + if (!object) + return NULL; + json_init (&object->json, JSON_OBJECT); + + if (hashtable_init (&object->hashtable, hash_string, string_equal, + g_free, value_decref)) { + g_free (object); + return NULL; + } + return &object->json; +} + +static void +json_delete_object (json_object_t * object) +{ + hashtable_close (&object->hashtable); + g_free (object); +} + +json_t * +json_object_get (const json_t * json, const char *key) +{ + json_object_t *object; + + if (!json_is_object (json)) + return NULL; + + object = json_to_object (json); + 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; + + if (!key || !value) + return -1; + + if (!json_is_object (json)) { + json_decref (value); + return -1; + } + object = json_to_object (json); + + 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) +{ + json_object_t *object; + + if (!json_is_object (json)) + return -1; + + object = json_to_object (json); + return hashtable_del (&object->hashtable, key); +} + +void * +json_object_iter (json_t * json) +{ + json_object_t *object; + + if (!json_is_object (json)) + return NULL; + + object = json_to_object (json); + return hashtable_iter (&object->hashtable); +} + +void * +json_object_iter_next (json_t * json, void *iter) +{ + json_object_t *object; + + if (!json_is_object (json) || iter == NULL) + return NULL; + + object = json_to_object (json); + return hashtable_iter_next (&object->hashtable, iter); +} + +const char * +json_object_iter_key (void *iter) +{ + if (!iter) + return NULL; + + return (const char *)hashtable_iter_key (iter); +} + +json_t * +json_object_iter_value (void *iter) +{ + if (!iter) + return NULL; + + return (json_t *) hashtable_iter_value (iter); +} + + +/*** array ***/ + +json_t * +json_array (void) +{ + json_array_t *array = g_malloc (sizeof (json_array_t)); + if (!array) + return NULL; + json_init (&array->json, JSON_ARRAY); + + array->entries = 0; + array->size = 0; + array->table = NULL; + + return &array->json; +} + +static void +json_delete_array (json_array_t * array) +{ + unsigned int i; + + for (i = 0; i < array->entries; i++) + json_decref (array->table[i]); + + g_free (array->table); + g_free (array); +} + +unsigned int +json_array_size (const json_t * json) +{ + if (!json_is_array (json)) + return 0; + + return json_to_array (json)->entries; +} + +json_t * +json_array_get (const json_t * json, unsigned int index) +{ + json_array_t *array; + if (!json_is_array (json)) + return NULL; + array = json_to_array (json); + + if (index >= array->entries) + return NULL; + + return array->table[index]; +} + +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->entries) { + json_decref (value); + return -1; + } + + json_decref (array->table[index]); + array->table[index] = value; + + return 0; +} + +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] = value; + array->entries++; + + return 0; +} + + +/*** string ***/ + +json_t * +json_string_nocheck (const char *value) +{ + json_string_t *string; + + if (!value) + return NULL; + + string = g_malloc (sizeof (json_string_t)); + if (!string) + return NULL; + json_init (&string->json, JSON_STRING); + + string->value = strdup (value); + if (!string->value) { + g_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)) + return NULL; + + return json_to_string (json)->value; +} + +static void +json_delete_string (json_string_t * string) +{ + g_free (string->value); + g_free (string); +} + + +/*** integer ***/ + +json_t * +json_integer (int value) +{ + json_integer_t *integer = g_malloc (sizeof (json_integer_t)); + if (!integer) + return NULL; + json_init (&integer->json, JSON_INTEGER); + + integer->value = value; + return &integer->json; +} + +int +json_integer_value (const json_t * json) +{ + if (!json_is_integer (json)) + return 0; + + return json_to_integer (json)->value; +} + +static void +json_delete_integer (json_integer_t * integer) +{ + g_free (integer); +} + + +/*** real ***/ + +json_t * +json_real (double value) +{ + json_real_t *real = g_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_real (json)->value; +} + +static void +json_delete_real (json_real_t * real) +{ + g_free (real); +} + + +/*** number ***/ + +double +json_number_value (const json_t * json) +{ + 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; +} + + +/*** simple values ***/ + +json_t * +json_true (void) +{ + static json_t the_true = { + .type = JSON_TRUE, + .refcount = 1 + }; + return json_incref (&the_true); +} + + +json_t * +json_false (void) +{ + static json_t the_false = { + .type = JSON_FALSE, + .refcount = 1 + }; + return json_incref (&the_false); +} + + +json_t * +json_null (void) +{ + static json_t the_null = { + .type = JSON_NULL, + .refcount = 1 + }; + return json_incref (&the_null); +} + + +/*** deletion ***/ + +void +json_delete (json_t * json) +{ + if (json_is_object (json)) + json_delete_object (json_to_object (json)); + + else if (json_is_array (json)) + json_delete_array (json_to_array (json)); + + else if (json_is_string (json)) + json_delete_string (json_to_string (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 */ +} |