Path: blob/master/compat/jansson/value.c
1295 views
/*1* Copyright (c) 2009-2013 Petri Lehtinen <[email protected]>2*3* Jansson is free software; you can redistribute it and/or modify4* it under the terms of the MIT license. See LICENSE for details.5*/67#ifndef _GNU_SOURCE8#define _GNU_SOURCE9#endif1011#include <stddef.h>12#include <stdlib.h>13#include <string.h>14#include <math.h>1516#include "jansson.h"17#include "hashtable.h"18#include "jansson_private.h"19#include "utf.h"2021/* Work around nonstandard isnan() and isinf() implementations */22#ifndef isnan23static JSON_INLINE int isnan(double x) { return x != x; }24#endif25#ifndef isinf26static JSON_INLINE int isinf(double x) { return !isnan(x) && isnan(x - x); }27#endif2829static JSON_INLINE void json_init(json_t *json, json_type type)30{31json->type = type;32json->refcount = 1;33}343536/*** object ***/3738json_t *json_object(void)39{40json_object_t *object = jsonp_malloc(sizeof(json_object_t));41if(!object)42return NULL;43json_init(&object->json, JSON_OBJECT);4445if(hashtable_init(&object->hashtable))46{47jsonp_free(object);48return NULL;49}5051object->serial = 0;52object->visited = 0;5354return &object->json;55}5657static void json_delete_object(json_object_t *object)58{59hashtable_close(&object->hashtable);60jsonp_free(object);61}6263size_t json_object_size(const json_t *json)64{65json_object_t *object;6667if(!json_is_object(json))68return 0;6970object = json_to_object(json);71return object->hashtable.size;72}7374json_t *json_object_get(const json_t *json, const char *key)75{76json_object_t *object;7778if(!json_is_object(json))79return NULL;8081object = json_to_object(json);82return hashtable_get(&object->hashtable, key);83}8485int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)86{87json_object_t *object;8889if(!value)90return -1;9192if(!key || !json_is_object(json) || json == value)93{94json_decref(value);95return -1;96}97object = json_to_object(json);9899if(hashtable_set(&object->hashtable, key, object->serial++, value))100{101json_decref(value);102return -1;103}104105return 0;106}107108int json_object_set_new(json_t *json, const char *key, json_t *value)109{110if(!key || !utf8_check_string(key, -1))111{112json_decref(value);113return -1;114}115116return json_object_set_new_nocheck(json, key, value);117}118119int json_object_del(json_t *json, const char *key)120{121json_object_t *object;122123if(!json_is_object(json))124return -1;125126object = json_to_object(json);127return hashtable_del(&object->hashtable, key);128}129130int json_object_clear(json_t *json)131{132json_object_t *object;133134if(!json_is_object(json))135return -1;136137object = json_to_object(json);138139hashtable_clear(&object->hashtable);140object->serial = 0;141142return 0;143}144145int json_object_update(json_t *object, json_t *other)146{147const char *key;148json_t *value;149150if(!json_is_object(object) || !json_is_object(other))151return -1;152153json_object_foreach(other, key, value) {154if(json_object_set_nocheck(object, key, value))155return -1;156}157158return 0;159}160161int json_object_update_existing(json_t *object, json_t *other)162{163const char *key;164json_t *value;165166if(!json_is_object(object) || !json_is_object(other))167return -1;168169json_object_foreach(other, key, value) {170if(json_object_get(object, key))171json_object_set_nocheck(object, key, value);172}173174return 0;175}176177int json_object_update_missing(json_t *object, json_t *other)178{179const char *key;180json_t *value;181182if(!json_is_object(object) || !json_is_object(other))183return -1;184185json_object_foreach(other, key, value) {186if(!json_object_get(object, key))187json_object_set_nocheck(object, key, value);188}189190return 0;191}192193void *json_object_iter(json_t *json)194{195json_object_t *object;196197if(!json_is_object(json))198return NULL;199200object = json_to_object(json);201return hashtable_iter(&object->hashtable);202}203204void *json_object_iter_at(json_t *json, const char *key)205{206json_object_t *object;207208if(!key || !json_is_object(json))209return NULL;210211object = json_to_object(json);212return hashtable_iter_at(&object->hashtable, key);213}214215void *json_object_iter_next(json_t *json, void *iter)216{217json_object_t *object;218219if(!json_is_object(json) || iter == NULL)220return NULL;221222object = json_to_object(json);223return hashtable_iter_next(&object->hashtable, iter);224}225226const char *json_object_iter_key(void *iter)227{228if(!iter)229return NULL;230231return hashtable_iter_key(iter);232}233234json_t *json_object_iter_value(void *iter)235{236if(!iter)237return NULL;238239return (json_t *)hashtable_iter_value(iter);240}241242int json_object_iter_set_new(json_t *json, void *iter, json_t *value)243{244if(!json_is_object(json) || !iter || !value)245return -1;246247hashtable_iter_set(iter, value);248return 0;249}250251void *json_object_key_to_iter(const char *key)252{253if(!key)254return NULL;255256return hashtable_key_to_iter(key);257}258259static int json_object_equal(json_t *object1, json_t *object2)260{261const char *key;262json_t *value1, *value2;263264if(json_object_size(object1) != json_object_size(object2))265return 0;266267json_object_foreach(object1, key, value1) {268value2 = json_object_get(object2, key);269270if(!json_equal(value1, value2))271return 0;272}273274return 1;275}276277static json_t *json_object_copy(json_t *object)278{279json_t *result;280281const char *key;282json_t *value;283284result = json_object();285if(!result)286return NULL;287288json_object_foreach(object, key, value)289json_object_set_nocheck(result, key, value);290291return result;292}293294static json_t *json_object_deep_copy(const json_t *object)295{296json_t *result;297void *iter;298299result = json_object();300if(!result)301return NULL;302303/* Cannot use json_object_foreach because object has to be cast304non-const */305iter = json_object_iter((json_t *)object);306while(iter) {307const char *key;308const json_t *value;309key = json_object_iter_key(iter);310value = json_object_iter_value(iter);311312json_object_set_new_nocheck(result, key, json_deep_copy(value));313iter = json_object_iter_next((json_t *)object, iter);314}315316return result;317}318319320/*** array ***/321322json_t *json_array(void)323{324json_array_t *array = jsonp_malloc(sizeof(json_array_t));325if(!array)326return NULL;327json_init(&array->json, JSON_ARRAY);328329array->entries = 0;330array->size = 8;331332array->table = jsonp_malloc(array->size * sizeof(json_t *));333if(!array->table) {334jsonp_free(array);335return NULL;336}337338array->visited = 0;339340return &array->json;341}342343static void json_delete_array(json_array_t *array)344{345size_t i;346347for(i = 0; i < array->entries; i++)348json_decref(array->table[i]);349350jsonp_free(array->table);351jsonp_free(array);352}353354size_t json_array_size(const json_t *json)355{356if(!json_is_array(json))357return 0;358359return json_to_array(json)->entries;360}361362json_t *json_array_get(const json_t *json, size_t index)363{364json_array_t *array;365if(!json_is_array(json))366return NULL;367array = json_to_array(json);368369if(index >= array->entries)370return NULL;371372return array->table[index];373}374375int json_array_set_new(json_t *json, size_t index, json_t *value)376{377json_array_t *array;378379if(!value)380return -1;381382if(!json_is_array(json) || json == value)383{384json_decref(value);385return -1;386}387array = json_to_array(json);388389if(index >= array->entries)390{391json_decref(value);392return -1;393}394395json_decref(array->table[index]);396array->table[index] = value;397398return 0;399}400401static void array_move(json_array_t *array, size_t dest,402size_t src, size_t count)403{404memmove(&array->table[dest], &array->table[src], count * sizeof(json_t *));405}406407static void array_copy(json_t **dest, size_t dpos,408json_t **src, size_t spos,409size_t count)410{411memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *));412}413414static json_t **json_array_grow(json_array_t *array,415size_t amount,416int copy)417{418size_t new_size;419json_t **old_table, **new_table;420421if(array->entries + amount <= array->size)422return array->table;423424old_table = array->table;425426new_size = max(array->size + amount, array->size * 2);427new_table = jsonp_malloc(new_size * sizeof(json_t *));428if(!new_table)429return NULL;430431array->size = new_size;432array->table = new_table;433434if(copy) {435array_copy(array->table, 0, old_table, 0, array->entries);436jsonp_free(old_table);437return array->table;438}439440return old_table;441}442443int json_array_append_new(json_t *json, json_t *value)444{445json_array_t *array;446447if(!value)448return -1;449450if(!json_is_array(json) || json == value)451{452json_decref(value);453return -1;454}455array = json_to_array(json);456457if(!json_array_grow(array, 1, 1)) {458json_decref(value);459return -1;460}461462array->table[array->entries] = value;463array->entries++;464465return 0;466}467468int json_array_insert_new(json_t *json, size_t index, json_t *value)469{470json_array_t *array;471json_t **old_table;472473if(!value)474return -1;475476if(!json_is_array(json) || json == value) {477json_decref(value);478return -1;479}480array = json_to_array(json);481482if(index > array->entries) {483json_decref(value);484return -1;485}486487old_table = json_array_grow(array, 1, 0);488if(!old_table) {489json_decref(value);490return -1;491}492493if(old_table != array->table) {494array_copy(array->table, 0, old_table, 0, index);495array_copy(array->table, index + 1, old_table, index,496array->entries - index);497jsonp_free(old_table);498}499else500array_move(array, index + 1, index, array->entries - index);501502array->table[index] = value;503array->entries++;504505return 0;506}507508int json_array_remove(json_t *json, size_t index)509{510json_array_t *array;511512if(!json_is_array(json))513return -1;514array = json_to_array(json);515516if(index >= array->entries)517return -1;518519json_decref(array->table[index]);520521/* If we're removing the last element, nothing has to be moved */522if(index < array->entries - 1)523array_move(array, index, index + 1, array->entries - index - 1);524525array->entries--;526527return 0;528}529530int json_array_clear(json_t *json)531{532json_array_t *array;533size_t i;534535if(!json_is_array(json))536return -1;537array = json_to_array(json);538539for(i = 0; i < array->entries; i++)540json_decref(array->table[i]);541542array->entries = 0;543return 0;544}545546int json_array_extend(json_t *json, json_t *other_json)547{548json_array_t *array, *other;549size_t i;550551if(!json_is_array(json) || !json_is_array(other_json))552return -1;553array = json_to_array(json);554other = json_to_array(other_json);555556if(!json_array_grow(array, other->entries, 1))557return -1;558559for(i = 0; i < other->entries; i++)560json_incref(other->table[i]);561562array_copy(array->table, array->entries, other->table, 0, other->entries);563564array->entries += other->entries;565return 0;566}567568static int json_array_equal(json_t *array1, json_t *array2)569{570size_t i, size;571572size = json_array_size(array1);573if(size != json_array_size(array2))574return 0;575576for(i = 0; i < size; i++)577{578json_t *value1, *value2;579580value1 = json_array_get(array1, i);581value2 = json_array_get(array2, i);582583if(!json_equal(value1, value2))584return 0;585}586587return 1;588}589590static json_t *json_array_copy(json_t *array)591{592json_t *result;593size_t i;594595result = json_array();596if(!result)597return NULL;598599for(i = 0; i < json_array_size(array); i++)600json_array_append(result, json_array_get(array, i));601602return result;603}604605static json_t *json_array_deep_copy(const json_t *array)606{607json_t *result;608size_t i;609610result = json_array();611if(!result)612return NULL;613614for(i = 0; i < json_array_size(array); i++)615json_array_append_new(result, json_deep_copy(json_array_get(array, i)));616617return result;618}619620/*** string ***/621622json_t *json_string_nocheck(const char *value)623{624json_string_t *string;625626if(!value)627return NULL;628629string = jsonp_malloc(sizeof(json_string_t));630if(!string)631return NULL;632json_init(&string->json, JSON_STRING);633634string->value = jsonp_strdup(value);635if(!string->value) {636jsonp_free(string);637return NULL;638}639640return &string->json;641}642643json_t *json_string(const char *value)644{645if(!value || !utf8_check_string(value, -1))646return NULL;647648return json_string_nocheck(value);649}650651const char *json_string_value(const json_t *json)652{653if(!json_is_string(json))654return NULL;655656return json_to_string(json)->value;657}658659int json_string_set_nocheck(json_t *json, const char *value)660{661char *dup;662json_string_t *string;663664if(!json_is_string(json) || !value)665return -1;666667dup = jsonp_strdup(value);668if(!dup)669return -1;670671string = json_to_string(json);672jsonp_free(string->value);673string->value = dup;674675return 0;676}677678int json_string_set(json_t *json, const char *value)679{680if(!value || !utf8_check_string(value, -1))681return -1;682683return json_string_set_nocheck(json, value);684}685686static void json_delete_string(json_string_t *string)687{688jsonp_free(string->value);689jsonp_free(string);690}691692static int json_string_equal(json_t *string1, json_t *string2)693{694return strcmp(json_string_value(string1), json_string_value(string2)) == 0;695}696697static json_t *json_string_copy(const json_t *string)698{699return json_string_nocheck(json_string_value(string));700}701702703/*** integer ***/704705json_t *json_integer(json_int_t value)706{707json_integer_t *integer = jsonp_malloc(sizeof(json_integer_t));708if(!integer)709return NULL;710json_init(&integer->json, JSON_INTEGER);711712integer->value = value;713return &integer->json;714}715716json_int_t json_integer_value(const json_t *json)717{718if(!json_is_integer(json))719return 0;720721return json_to_integer(json)->value;722}723724int json_integer_set(json_t *json, json_int_t value)725{726if(!json_is_integer(json))727return -1;728729json_to_integer(json)->value = value;730731return 0;732}733734static void json_delete_integer(json_integer_t *integer)735{736jsonp_free(integer);737}738739static int json_integer_equal(json_t *integer1, json_t *integer2)740{741return json_integer_value(integer1) == json_integer_value(integer2);742}743744static json_t *json_integer_copy(const json_t *integer)745{746return json_integer(json_integer_value(integer));747}748749750/*** real ***/751752json_t *json_real(double value)753{754json_real_t *real;755756if(isnan(value) || isinf(value))757return NULL;758759real = jsonp_malloc(sizeof(json_real_t));760if(!real)761return NULL;762json_init(&real->json, JSON_REAL);763764real->value = value;765return &real->json;766}767768double json_real_value(const json_t *json)769{770if(!json_is_real(json))771return 0;772773return json_to_real(json)->value;774}775776int json_real_set(json_t *json, double value)777{778if(!json_is_real(json) || isnan(value) || isinf(value))779return -1;780781json_to_real(json)->value = value;782783return 0;784}785786static void json_delete_real(json_real_t *real)787{788jsonp_free(real);789}790791static int json_real_equal(json_t *real1, json_t *real2)792{793return json_real_value(real1) == json_real_value(real2);794}795796static json_t *json_real_copy(const json_t *real)797{798return json_real(json_real_value(real));799}800801802/*** number ***/803804double json_number_value(const json_t *json)805{806if(json_is_integer(json))807return (double)json_integer_value(json);808else if(json_is_real(json))809return json_real_value(json);810else811return 0.0;812}813814815/*** simple values ***/816817json_t *json_true(void)818{819static json_t the_true = {JSON_TRUE, (size_t)-1};820return &the_true;821}822823824json_t *json_false(void)825{826static json_t the_false = {JSON_FALSE, (size_t)-1};827return &the_false;828}829830831json_t *json_null(void)832{833static json_t the_null = {JSON_NULL, (size_t)-1};834return &the_null;835}836837838/*** deletion ***/839840void json_delete(json_t *json)841{842if(json_is_object(json))843json_delete_object(json_to_object(json));844845else if(json_is_array(json))846json_delete_array(json_to_array(json));847848else if(json_is_string(json))849json_delete_string(json_to_string(json));850851else if(json_is_integer(json))852json_delete_integer(json_to_integer(json));853854else if(json_is_real(json))855json_delete_real(json_to_real(json));856857/* json_delete is not called for true, false or null */858}859860861/*** equality ***/862863int json_equal(json_t *json1, json_t *json2)864{865if(!json1 || !json2)866return 0;867868if(json_typeof(json1) != json_typeof(json2))869return 0;870871/* this covers true, false and null as they are singletons */872if(json1 == json2)873return 1;874875if(json_is_object(json1))876return json_object_equal(json1, json2);877878if(json_is_array(json1))879return json_array_equal(json1, json2);880881if(json_is_string(json1))882return json_string_equal(json1, json2);883884if(json_is_integer(json1))885return json_integer_equal(json1, json2);886887if(json_is_real(json1))888return json_real_equal(json1, json2);889890return 0;891}892893894/*** copying ***/895896json_t *json_copy(json_t *json)897{898if(!json)899return NULL;900901if(json_is_object(json))902return json_object_copy(json);903904if(json_is_array(json))905return json_array_copy(json);906907if(json_is_string(json))908return json_string_copy(json);909910if(json_is_integer(json))911return json_integer_copy(json);912913if(json_is_real(json))914return json_real_copy(json);915916if(json_is_true(json) || json_is_false(json) || json_is_null(json))917return json;918919return NULL;920}921922json_t *json_deep_copy(const json_t *json)923{924if(!json)925return NULL;926927if(json_is_object(json))928return json_object_deep_copy(json);929930if(json_is_array(json))931return json_array_deep_copy(json);932933/* for the rest of the types, deep copying doesn't differ from934shallow copying */935936if(json_is_string(json))937return json_string_copy(json);938939if(json_is_integer(json))940return json_integer_copy(json);941942if(json_is_real(json))943return json_real_copy(json);944945if(json_is_true(json) || json_is_false(json) || json_is_null(json))946return (json_t *)json;947948return NULL;949}950951952