Blame json_object.c

Packit Service def718
/*
Packit Service def718
 * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
Packit Service def718
 *
Packit Service def718
 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
Packit Service def718
 * Michael Clark <michael@metaparadigm.com>
Packit Service def718
 * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
Packit Service def718
 *
Packit Service def718
 * This library is free software; you can redistribute it and/or modify
Packit Service def718
 * it under the terms of the MIT license. See COPYING for details.
Packit Service def718
 *
Packit Service def718
 */
Packit Service def718
Packit Service def718
#include "config.h"
Packit Service def718
Packit Service def718
#include "strerror_override.h"
Packit Service def718
Packit Service def718
#include <assert.h>
Packit Service def718
#include <ctype.h>
Packit Service def718
#include <stdio.h>
Packit Service def718
#include <stdlib.h>
Packit Service def718
#include <stddef.h>
Packit Service def718
#include <string.h>
Packit Service def718
#include <math.h>
Packit Service def718
Packit Service def718
#include "debug.h"
Packit Service def718
#include "printbuf.h"
Packit Service def718
#include "linkhash.h"
Packit Service def718
#include "arraylist.h"
Packit Service def718
#include "json_inttypes.h"
Packit Service def718
#include "json_object.h"
Packit Service def718
#include "json_object_private.h"
Packit Service def718
#include "json_util.h"
Packit Service def718
#include "math_compat.h"
Packit Service def718
#include "strdup_compat.h"
Packit Service def718
#include "snprintf_compat.h"
Packit Service def718
Packit Service def718
#if SIZEOF_LONG_LONG != SIZEOF_INT64_T
Packit Service def718
#error "The long long type isn't 64-bits"
Packit Service def718
#endif
Packit Service def718
Packit Service def718
// Don't define this.  It's not thread-safe.
Packit Service def718
/* #define REFCOUNT_DEBUG 1 */
Packit Service def718
Packit Service def718
const char *json_number_chars = "0123456789.+-eE";
Packit Service def718
const char *json_hex_chars = "0123456789abcdefABCDEF";
Packit Service def718
Packit Service def718
static void json_object_generic_delete(struct json_object* jso);
Packit Service def718
static struct json_object* json_object_new(enum json_type o_type);
Packit Service def718
Packit Service def718
static json_object_to_json_string_fn json_object_object_to_json_string;
Packit Service def718
static json_object_to_json_string_fn json_object_boolean_to_json_string;
Packit Service def718
static json_object_to_json_string_fn json_object_double_to_json_string_default;
Packit Service def718
static json_object_to_json_string_fn json_object_int_to_json_string;
Packit Service def718
static json_object_to_json_string_fn json_object_string_to_json_string;
Packit Service def718
static json_object_to_json_string_fn json_object_array_to_json_string;
Packit Service def718
Packit Service def718
Packit Service def718
/* ref count debugging */
Packit Service def718
Packit Service def718
#ifdef REFCOUNT_DEBUG
Packit Service def718
Packit Service def718
static struct lh_table *json_object_table;
Packit Service def718
Packit Service def718
static void json_object_init(void) __attribute__ ((constructor));
Packit Service def718
static void json_object_init(void) {
Packit Service def718
	MC_DEBUG("json_object_init: creating object table\n");
Packit Service def718
	json_object_table = lh_kptr_table_new(128, NULL);
Packit Service def718
}
Packit Service def718
Packit Service def718
static void json_object_fini(void) __attribute__ ((destructor));
Packit Service def718
static void json_object_fini(void)
Packit Service def718
{
Packit Service def718
	struct lh_entry *ent;
Packit Service def718
	if (MC_GET_DEBUG())
Packit Service def718
	{
Packit Service def718
		if (json_object_table->count)
Packit Service def718
		{
Packit Service def718
			MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
Packit Service def718
			   json_object_table->count);
Packit Service def718
			lh_foreach(json_object_table, ent)
Packit Service def718
			{
Packit Service def718
				struct json_object* obj =
Packit Service def718
				  (struct json_object*) lh_entry_v(ent);
Packit Service def718
				MC_DEBUG("\t%s:%p\n",
Packit Service def718
					 json_type_to_name(obj->o_type), obj);
Packit Service def718
			}
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
	MC_DEBUG("json_object_fini: freeing object table\n");
Packit Service def718
	lh_table_free(json_object_table);
Packit Service def718
}
Packit Service def718
#endif /* REFCOUNT_DEBUG */
Packit Service def718
Packit Service def718
Packit Service def718
/* helper for accessing the optimized string data component in json_object
Packit Service def718
 */
Packit Service def718
static const char *
Packit Service def718
get_string_component(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	return (jso->o.c_string.len < LEN_DIRECT_STRING_DATA) ?
Packit Service def718
		   jso->o.c_string.str.data : jso->o.c_string.str.ptr;
Packit Service def718
}
Packit Service def718
Packit Service def718
/* string escaping */
Packit Service def718
Packit Service def718
static int json_escape_str(struct printbuf *pb, const char *str, int len, int flags)
Packit Service def718
{
Packit Service def718
	int pos = 0, start_offset = 0;
Packit Service def718
	unsigned char c;
Packit Service def718
	while (len--)
Packit Service def718
	{
Packit Service def718
		c = str[pos];
Packit Service def718
		switch(c)
Packit Service def718
		{
Packit Service def718
		case '\b':
Packit Service def718
		case '\n':
Packit Service def718
		case '\r':
Packit Service def718
		case '\t':
Packit Service def718
		case '\f':
Packit Service def718
		case '"':
Packit Service def718
		case '\\':
Packit Service def718
		case '/':
Packit Service def718
			if((flags & JSON_C_TO_STRING_NOSLASHESCAPE) && c == '/')
Packit Service def718
			{
Packit Service def718
				pos++;
Packit Service def718
				break;
Packit Service def718
			}
Packit Service def718
Packit Service def718
			if(pos - start_offset > 0)
Packit Service def718
				printbuf_memappend(pb, str + start_offset, pos - start_offset);
Packit Service def718
Packit Service def718
			if(c == '\b') printbuf_memappend(pb, "\\b", 2);
Packit Service def718
			else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
Packit Service def718
			else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
Packit Service def718
			else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
Packit Service def718
			else if(c == '\f') printbuf_memappend(pb, "\\f", 2);
Packit Service def718
			else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
Packit Service def718
			else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
Packit Service def718
			else if(c == '/') printbuf_memappend(pb, "\\/", 2);
Packit Service def718
Packit Service def718
			start_offset = ++pos;
Packit Service def718
			break;
Packit Service def718
		default:
Packit Service def718
			if(c < ' ')
Packit Service def718
			{
Packit Service def718
				char sbuf[7];
Packit Service def718
				if(pos - start_offset > 0)
Packit Service def718
					printbuf_memappend(pb,
Packit Service def718
							   str + start_offset,
Packit Service def718
							   pos - start_offset);
Packit Service def718
				snprintf(sbuf, sizeof(sbuf),
Packit Service def718
					 "\\u00%c%c",
Packit Service def718
					 json_hex_chars[c >> 4],
Packit Service def718
					 json_hex_chars[c & 0xf]);
Packit Service def718
				printbuf_memappend_fast(pb, sbuf, (int) sizeof(sbuf) - 1);
Packit Service def718
				start_offset = ++pos;
Packit Service def718
			} else
Packit Service def718
				pos++;
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
	if (pos - start_offset > 0)
Packit Service def718
		printbuf_memappend(pb, str + start_offset, pos - start_offset);
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* reference counting */
Packit Service def718
Packit Service def718
extern struct json_object* json_object_get(struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if (!jso) return jso;
Packit Service def718
Packit Service def718
#if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING)
Packit Service def718
	__sync_add_and_fetch(&jso->_ref_count, 1);
Packit Service def718
#else
Packit Service def718
	++jso->_ref_count;
Packit Service def718
#endif        
Packit Service def718
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_put(struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if(!jso) return 0;
Packit Service def718
Packit Service def718
	/* Avoid invalid free and crash explicitly instead of (silently)
Packit Service def718
	 * segfaulting.
Packit Service def718
	 */
Packit Service def718
	assert(jso->_ref_count > 0);
Packit Service def718
Packit Service def718
#if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING)
Packit Service def718
	/* Note: this only allow the refcount to remain correct
Packit Service def718
	 * when multiple threads are adjusting it.  It is still an error 
Packit Service def718
	 * for a thread to decrement the refcount if it doesn't "own" it,
Packit Service def718
	 * as that can result in the thread that loses the race to 0
Packit Service def718
	 * operating on an already-freed object.
Packit Service def718
	 */
Packit Service def718
	if (__sync_sub_and_fetch(&jso->_ref_count, 1) > 0) return 0;
Packit Service def718
#else
Packit Service def718
	if (--jso->_ref_count > 0) return 0;
Packit Service def718
#endif
Packit Service def718
Packit Service def718
	if (jso->_user_delete)
Packit Service def718
		jso->_user_delete(jso, jso->_userdata);
Packit Service def718
	jso->_delete(jso);
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* generic object construction and destruction parts */
Packit Service def718
Packit Service def718
static void json_object_generic_delete(struct json_object* jso)
Packit Service def718
{
Packit Service def718
#ifdef REFCOUNT_DEBUG
Packit Service def718
	MC_DEBUG("json_object_delete_%s: %p\n",
Packit Service def718
	   json_type_to_name(jso->o_type), jso);
Packit Service def718
	lh_table_delete(json_object_table, jso);
Packit Service def718
#endif /* REFCOUNT_DEBUG */
Packit Service def718
	printbuf_free(jso->_pb);
Packit Service def718
	free(jso);
Packit Service def718
}
Packit Service def718
Packit Service def718
static struct json_object* json_object_new(enum json_type o_type)
Packit Service def718
{
Packit Service def718
	struct json_object *jso;
Packit Service def718
Packit Service def718
	jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->o_type = o_type;
Packit Service def718
	jso->_ref_count = 1;
Packit Service def718
	jso->_delete = &json_object_generic_delete;
Packit Service def718
#ifdef REFCOUNT_DEBUG
Packit Service def718
	lh_table_insert(json_object_table, jso, jso);
Packit Service def718
	MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso);
Packit Service def718
#endif /* REFCOUNT_DEBUG */
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* type checking functions */
Packit Service def718
Packit Service def718
int json_object_is_type(const struct json_object *jso, enum json_type type)
Packit Service def718
{
Packit Service def718
	if (!jso)
Packit Service def718
		return (type == json_type_null);
Packit Service def718
	return (jso->o_type == type);
Packit Service def718
}
Packit Service def718
Packit Service def718
enum json_type json_object_get_type(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if (!jso)
Packit Service def718
		return json_type_null;
Packit Service def718
	return jso->o_type;
Packit Service def718
}
Packit Service def718
Packit Service def718
void* json_object_get_userdata(json_object *jso) {
Packit Service def718
	return jso ? jso->_userdata : NULL;
Packit Service def718
}
Packit Service def718
Packit Service def718
void json_object_set_userdata(json_object *jso, void *userdata,
Packit Service def718
			      json_object_delete_fn *user_delete)
Packit Service def718
{
Packit Service def718
	// Can't return failure, so abort if we can't perform the operation.
Packit Service def718
	assert(jso != NULL);
Packit Service def718
Packit Service def718
	// First, clean up any previously existing user info
Packit Service def718
	if (jso->_user_delete)
Packit Service def718
		jso->_user_delete(jso, jso->_userdata);
Packit Service def718
Packit Service def718
	jso->_userdata = userdata;
Packit Service def718
	jso->_user_delete = user_delete;
Packit Service def718
}
Packit Service def718
Packit Service def718
/* set a custom conversion to string */
Packit Service def718
Packit Service def718
void json_object_set_serializer(json_object *jso,
Packit Service def718
	json_object_to_json_string_fn *to_string_func,
Packit Service def718
	void *userdata,
Packit Service def718
	json_object_delete_fn *user_delete)
Packit Service def718
{
Packit Service def718
	json_object_set_userdata(jso, userdata, user_delete);
Packit Service def718
Packit Service def718
	if (to_string_func == NULL)
Packit Service def718
	{
Packit Service def718
		// Reset to the standard serialization function
Packit Service def718
		switch(jso->o_type)
Packit Service def718
		{
Packit Service def718
		case json_type_null:
Packit Service def718
			jso->_to_json_string = NULL;
Packit Service def718
			break;
Packit Service def718
		case json_type_boolean:
Packit Service def718
			jso->_to_json_string = &json_object_boolean_to_json_string;
Packit Service def718
			break;
Packit Service def718
		case json_type_double:
Packit Service def718
			jso->_to_json_string = &json_object_double_to_json_string_default;
Packit Service def718
			break;
Packit Service def718
		case json_type_int:
Packit Service def718
			jso->_to_json_string = &json_object_int_to_json_string;
Packit Service def718
			break;
Packit Service def718
		case json_type_object:
Packit Service def718
			jso->_to_json_string = &json_object_object_to_json_string;
Packit Service def718
			break;
Packit Service def718
		case json_type_array:
Packit Service def718
			jso->_to_json_string = &json_object_array_to_json_string;
Packit Service def718
			break;
Packit Service def718
		case json_type_string:
Packit Service def718
			jso->_to_json_string = &json_object_string_to_json_string;
Packit Service def718
			break;
Packit Service def718
		}
Packit Service def718
		return;
Packit Service def718
	}
Packit Service def718
Packit Service def718
	jso->_to_json_string = to_string_func;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* extended conversion to string */
Packit Service def718
Packit Service def718
const char* json_object_to_json_string_length(struct json_object *jso, int flags, size_t *length)
Packit Service def718
{
Packit Service def718
	const char *r = NULL;
Packit Service def718
	size_t s = 0;
Packit Service def718
Packit Service def718
	if (!jso)
Packit Service def718
	{
Packit Service def718
		s = 4;
Packit Service def718
		r = "null";
Packit Service def718
	}
Packit Service def718
	else if ((jso->_pb) || (jso->_pb = printbuf_new()))
Packit Service def718
	{
Packit Service def718
		printbuf_reset(jso->_pb);
Packit Service def718
Packit Service def718
		if(jso->_to_json_string(jso, jso->_pb, 0, flags) >= 0)
Packit Service def718
		{
Packit Service def718
			s = (size_t)jso->_pb->bpos;
Packit Service def718
			r = jso->_pb->buf;
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
Packit Service def718
	if (length)
Packit Service def718
		*length = s;
Packit Service def718
	return r;
Packit Service def718
}
Packit Service def718
Packit Service def718
const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
Packit Service def718
{
Packit Service def718
	return json_object_to_json_string_length(jso, flags, NULL);
Packit Service def718
}
Packit Service def718
Packit Service def718
/* backwards-compatible conversion to string */
Packit Service def718
Packit Service def718
const char* json_object_to_json_string(struct json_object *jso)
Packit Service def718
{
Packit Service def718
	return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
Packit Service def718
}
Packit Service def718
Packit Service def718
static void indent(struct printbuf *pb, int level, int flags)
Packit Service def718
{
Packit Service def718
	if (flags & JSON_C_TO_STRING_PRETTY)
Packit Service def718
	{
Packit Service def718
		if (flags & JSON_C_TO_STRING_PRETTY_TAB)
Packit Service def718
		{
Packit Service def718
			printbuf_memset(pb, -1, '\t', level);
Packit Service def718
		}
Packit Service def718
		else
Packit Service def718
		{
Packit Service def718
			printbuf_memset(pb, -1, ' ', level * 2);
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
/* json_object_object */
Packit Service def718
Packit Service def718
static int json_object_object_to_json_string(struct json_object* jso,
Packit Service def718
					     struct printbuf *pb,
Packit Service def718
					     int level,
Packit Service def718
					     int flags)
Packit Service def718
{
Packit Service def718
	int had_children = 0;
Packit Service def718
	struct json_object_iter iter;
Packit Service def718
Packit Service def718
	printbuf_strappend(pb, "{" /*}*/);
Packit Service def718
	if (flags & JSON_C_TO_STRING_PRETTY)
Packit Service def718
		printbuf_strappend(pb, "\n");
Packit Service def718
	json_object_object_foreachC(jso, iter)
Packit Service def718
	{
Packit Service def718
		if (had_children)
Packit Service def718
		{
Packit Service def718
			printbuf_strappend(pb, ",");
Packit Service def718
			if (flags & JSON_C_TO_STRING_PRETTY)
Packit Service def718
				printbuf_strappend(pb, "\n");
Packit Service def718
		}
Packit Service def718
		had_children = 1;
Packit Service def718
		if (flags & JSON_C_TO_STRING_SPACED)
Packit Service def718
			printbuf_strappend(pb, " ");
Packit Service def718
		indent(pb, level+1, flags);
Packit Service def718
		printbuf_strappend(pb, "\"");
Packit Service def718
		json_escape_str(pb, iter.key, strlen(iter.key), flags);
Packit Service def718
		if (flags & JSON_C_TO_STRING_SPACED)
Packit Service def718
			printbuf_strappend(pb, "\": ");
Packit Service def718
		else
Packit Service def718
			printbuf_strappend(pb, "\":");
Packit Service def718
		if(iter.val == NULL)
Packit Service def718
			printbuf_strappend(pb, "null");
Packit Service def718
		else
Packit Service def718
			if (iter.val->_to_json_string(iter.val, pb, level+1,flags) < 0)
Packit Service def718
				return -1;
Packit Service def718
	}
Packit Service def718
	if (flags & JSON_C_TO_STRING_PRETTY)
Packit Service def718
	{
Packit Service def718
		if (had_children)
Packit Service def718
			printbuf_strappend(pb, "\n");
Packit Service def718
		indent(pb,level,flags);
Packit Service def718
	}
Packit Service def718
	if (flags & JSON_C_TO_STRING_SPACED)
Packit Service def718
		return printbuf_strappend(pb, /*{*/ " }");
Packit Service def718
	else
Packit Service def718
		return printbuf_strappend(pb, /*{*/ "}");
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
static void json_object_lh_entry_free(struct lh_entry *ent)
Packit Service def718
{
Packit Service def718
	if (!ent->k_is_constant)
Packit Service def718
		free(lh_entry_k(ent));
Packit Service def718
	json_object_put((struct json_object*)lh_entry_v(ent));
Packit Service def718
}
Packit Service def718
Packit Service def718
static void json_object_object_delete(struct json_object* jso)
Packit Service def718
{
Packit Service def718
	lh_table_free(jso->o.c_object);
Packit Service def718
	json_object_generic_delete(jso);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_object(void)
Packit Service def718
{
Packit Service def718
	struct json_object *jso = json_object_new(json_type_object);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_delete = &json_object_object_delete;
Packit Service def718
	jso->_to_json_string = &json_object_object_to_json_string;
Packit Service def718
	jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
Packit Service def718
					     &json_object_lh_entry_free);
Packit Service def718
	if (!jso->o.c_object)
Packit Service def718
	{
Packit Service def718
		json_object_generic_delete(jso);
Packit Service def718
		errno = ENOMEM;
Packit Service def718
		return NULL;
Packit Service def718
	}
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct lh_table* json_object_get_object(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	switch(jso->o_type)
Packit Service def718
	{
Packit Service def718
	case json_type_object:
Packit Service def718
		return jso->o.c_object;
Packit Service def718
	default:
Packit Service def718
		return NULL;
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_object_add_ex(struct json_object* jso,
Packit Service def718
	const char *const key,
Packit Service def718
	struct json_object *const val,
Packit Service def718
	const unsigned opts)
Packit Service def718
{
Packit Service def718
	struct json_object *existing_value = NULL;
Packit Service def718
	struct lh_entry *existing_entry;
Packit Service def718
	unsigned long hash;
Packit Service def718
Packit Service def718
	assert(json_object_get_type(jso) == json_type_object);
Packit Service def718
Packit Service def718
	// We lookup the entry and replace the value, rather than just deleting
Packit Service def718
	// and re-adding it, so the existing key remains valid.
Packit Service def718
	hash = lh_get_hash(jso->o.c_object, (const void *)key);
Packit Service def718
	existing_entry = (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW) ? NULL : 
Packit Service def718
			      lh_table_lookup_entry_w_hash(jso->o.c_object,
Packit Service def718
							   (const void *)key, hash);
Packit Service def718
Packit Service def718
	// The caller must avoid creating loops in the object tree, but do a
Packit Service def718
	// quick check anyway to make sure we're not creating a trivial loop.
Packit Service def718
	if (jso == val)
Packit Service def718
		return -1;
Packit Service def718
Packit Service def718
	if (!existing_entry)
Packit Service def718
	{
Packit Service def718
		const void *const k = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ?
Packit Service def718
					(const void *)key : strdup(key);
Packit Service def718
		if (k == NULL)
Packit Service def718
			return -1;
Packit Service def718
		return lh_table_insert_w_hash(jso->o.c_object, k, val, hash, opts);
Packit Service def718
	}
Packit Service def718
	existing_value = (json_object *) lh_entry_v(existing_entry);
Packit Service def718
	if (existing_value)
Packit Service def718
		json_object_put(existing_value);
Packit Service def718
	existing_entry->v = val;
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_object_add(struct json_object* jso, const char *key,
Packit Service def718
                           struct json_object *val)
Packit Service def718
{
Packit Service def718
	return json_object_object_add_ex(jso, key, val, 0);
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
int json_object_object_length(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_object);
Packit Service def718
	return lh_table_length(jso->o.c_object);
Packit Service def718
}
Packit Service def718
Packit Service def718
size_t json_c_object_sizeof(void)
Packit Service def718
{
Packit Service def718
	return sizeof(struct json_object);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_object_get(const struct json_object* jso,
Packit Service def718
					   const char *key)
Packit Service def718
{
Packit Service def718
	struct json_object *result = NULL;
Packit Service def718
	json_object_object_get_ex(jso, key, &result);
Packit Service def718
	return result;
Packit Service def718
}
Packit Service def718
Packit Service def718
json_bool json_object_object_get_ex(const struct json_object* jso, const char *key,
Packit Service def718
				    struct json_object **value)
Packit Service def718
{
Packit Service def718
	if (value != NULL)
Packit Service def718
		*value = NULL;
Packit Service def718
Packit Service def718
	if (NULL == jso)
Packit Service def718
		return FALSE;
Packit Service def718
Packit Service def718
	switch(jso->o_type)
Packit Service def718
	{
Packit Service def718
	case json_type_object:
Packit Service def718
		return lh_table_lookup_ex(jso->o.c_object, (const void *) key,
Packit Service def718
					  (void**) value);
Packit Service def718
	default:
Packit Service def718
		if (value != NULL)
Packit Service def718
			*value = NULL;
Packit Service def718
		return FALSE;
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
void json_object_object_del(struct json_object* jso, const char *key)
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_object);
Packit Service def718
	lh_table_delete(jso->o.c_object, key);
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* json_object_boolean */
Packit Service def718
Packit Service def718
static int json_object_boolean_to_json_string(struct json_object* jso,
Packit Service def718
					      struct printbuf *pb,
Packit Service def718
					      int level,
Packit Service def718
					      int flags)
Packit Service def718
{
Packit Service def718
	if (jso->o.c_boolean)
Packit Service def718
		return printbuf_strappend(pb, "true");
Packit Service def718
	return printbuf_strappend(pb, "false");
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_boolean(json_bool b)
Packit Service def718
{
Packit Service def718
	struct json_object *jso = json_object_new(json_type_boolean);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_to_json_string = &json_object_boolean_to_json_string;
Packit Service def718
	jso->o.c_boolean = b;
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
json_bool json_object_get_boolean(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if (!jso)
Packit Service def718
		return FALSE;
Packit Service def718
	switch(jso->o_type)
Packit Service def718
	{
Packit Service def718
	case json_type_boolean:
Packit Service def718
		return jso->o.c_boolean;
Packit Service def718
	case json_type_int:
Packit Service def718
		return (jso->o.c_int64 != 0);
Packit Service def718
	case json_type_double:
Packit Service def718
		return (jso->o.c_double != 0);
Packit Service def718
	case json_type_string:
Packit Service def718
		return (jso->o.c_string.len != 0);
Packit Service def718
	default:
Packit Service def718
		return FALSE;
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_set_boolean(struct json_object *jso,json_bool new_value){
Packit Service def718
	if (!jso || jso->o_type!=json_type_boolean)
Packit Service def718
		return 0;
Packit Service def718
	jso->o.c_boolean=new_value;
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* json_object_int */
Packit Service def718
Packit Service def718
static int json_object_int_to_json_string(struct json_object* jso,
Packit Service def718
					  struct printbuf *pb,
Packit Service def718
					  int level,
Packit Service def718
					  int flags)
Packit Service def718
{
Packit Service def718
	/* room for 19 digits, the sign char, and a null term */
Packit Service def718
	char sbuf[21];
Packit Service def718
	snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int64);
Packit Service def718
	return printbuf_memappend (pb, sbuf, strlen(sbuf));
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_int(int32_t i)
Packit Service def718
{
Packit Service def718
	struct json_object *jso = json_object_new(json_type_int);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_to_json_string = &json_object_int_to_json_string;
Packit Service def718
	jso->o.c_int64 = i;
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
int32_t json_object_get_int(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
  int64_t cint64;
Packit Service def718
  enum json_type o_type;
Packit Service def718
Packit Service def718
  if(!jso) return 0;
Packit Service def718
Packit Service def718
  o_type = jso->o_type;
Packit Service def718
  cint64 = jso->o.c_int64;
Packit Service def718
Packit Service def718
  if (o_type == json_type_string)
Packit Service def718
  {
Packit Service def718
	/*
Packit Service def718
	 * Parse strings into 64-bit numbers, then use the
Packit Service def718
	 * 64-to-32-bit number handling below.
Packit Service def718
	 */
Packit Service def718
	if (json_parse_int64(get_string_component(jso), &cint64) != 0)
Packit Service def718
		return 0; /* whoops, it didn't work. */
Packit Service def718
	o_type = json_type_int;
Packit Service def718
  }
Packit Service def718
Packit Service def718
  switch(o_type) {
Packit Service def718
  case json_type_int:
Packit Service def718
	/* Make sure we return the correct values for out of range numbers. */
Packit Service def718
	if (cint64 <= INT32_MIN)
Packit Service def718
		return INT32_MIN;
Packit Service def718
	if (cint64 >= INT32_MAX)
Packit Service def718
		return INT32_MAX;
Packit Service def718
	return (int32_t) cint64;
Packit Service def718
  case json_type_double:
Packit Service def718
    if (jso->o.c_double <= INT32_MIN)
Packit Service def718
      return INT32_MIN;
Packit Service def718
    if (jso->o.c_double >= INT32_MAX)
Packit Service def718
      return INT32_MAX;
Packit Service def718
    return (int32_t)jso->o.c_double;
Packit Service def718
  case json_type_boolean:
Packit Service def718
    return jso->o.c_boolean;
Packit Service def718
  default:
Packit Service def718
    return 0;
Packit Service def718
  }
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_set_int(struct json_object *jso,int new_value){
Packit Service def718
	if (!jso || jso->o_type!=json_type_int)
Packit Service def718
		return 0;
Packit Service def718
	jso->o.c_int64=new_value;
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_int64(int64_t i)
Packit Service def718
{
Packit Service def718
	struct json_object *jso = json_object_new(json_type_int);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_to_json_string = &json_object_int_to_json_string;
Packit Service def718
	jso->o.c_int64 = i;
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
int64_t json_object_get_int64(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	int64_t cint;
Packit Service def718
Packit Service def718
	if (!jso)
Packit Service def718
		return 0;
Packit Service def718
	switch(jso->o_type)
Packit Service def718
	{
Packit Service def718
	case json_type_int:
Packit Service def718
		return jso->o.c_int64;
Packit Service def718
	case json_type_double:
Packit Service def718
		if (jso->o.c_double >= INT64_MAX)
Packit Service def718
			return INT64_MAX;
Packit Service def718
		if (jso->o.c_double <= INT64_MIN)
Packit Service def718
			return INT64_MIN;
Packit Service def718
		return (int64_t)jso->o.c_double;
Packit Service def718
	case json_type_boolean:
Packit Service def718
		return jso->o.c_boolean;
Packit Service def718
	case json_type_string:
Packit Service def718
		if (json_parse_int64(get_string_component(jso), &cint) == 0)
Packit Service def718
			return cint;
Packit Service def718
		/* FALLTHRU */
Packit Service def718
	default:
Packit Service def718
		return 0;
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_set_int64(struct json_object *jso,int64_t new_value){
Packit Service def718
	if (!jso || jso->o_type!=json_type_int)
Packit Service def718
		return 0;
Packit Service def718
	jso->o.c_int64=new_value;
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_int_inc(struct json_object *jso, int64_t val) {
Packit Service def718
	if (!jso || jso->o_type != json_type_int)
Packit Service def718
		return 0;
Packit Service def718
	if (val > 0 && jso->o.c_int64 > INT64_MAX - val) {
Packit Service def718
		jso->o.c_int64 = INT64_MAX;
Packit Service def718
	} else if (val < 0 && jso->o.c_int64 < INT64_MIN - val) {
Packit Service def718
		jso->o.c_int64 = INT64_MIN;
Packit Service def718
	} else {
Packit Service def718
		jso->o.c_int64 += val;
Packit Service def718
	}
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
/* json_object_double */
Packit Service def718
Packit Service def718
#if defined(HAVE___THREAD)
Packit Service def718
// i.e. __thread or __declspec(thread)
Packit Service def718
static SPEC___THREAD char *tls_serialization_float_format = NULL;
Packit Service def718
#endif
Packit Service def718
static char *global_serialization_float_format = NULL;
Packit Service def718
Packit Service def718
int json_c_set_serialization_double_format(const char *double_format, int global_or_thread)
Packit Service def718
{
Packit Service def718
	if (global_or_thread == JSON_C_OPTION_GLOBAL)
Packit Service def718
	{
Packit Service def718
#if defined(HAVE___THREAD)
Packit Service def718
		if (tls_serialization_float_format)
Packit Service def718
		{
Packit Service def718
			free(tls_serialization_float_format);
Packit Service def718
			tls_serialization_float_format = NULL;
Packit Service def718
		}
Packit Service def718
#endif
Packit Service def718
		if (global_serialization_float_format)
Packit Service def718
			free(global_serialization_float_format);
Packit Service def718
		global_serialization_float_format = double_format ? strdup(double_format) : NULL;
Packit Service def718
	}
Packit Service def718
	else if (global_or_thread == JSON_C_OPTION_THREAD)
Packit Service def718
	{
Packit Service def718
#if defined(HAVE___THREAD)
Packit Service def718
		if (tls_serialization_float_format)
Packit Service def718
		{
Packit Service def718
			free(tls_serialization_float_format);
Packit Service def718
			tls_serialization_float_format = NULL;
Packit Service def718
		}
Packit Service def718
		tls_serialization_float_format = double_format ? strdup(double_format) : NULL;
Packit Service def718
#else
Packit Service def718
		_json_c_set_last_err("json_c_set_option: not compiled with __thread support\n");
Packit Service def718
		return -1;
Packit Service def718
#endif
Packit Service def718
	}
Packit Service def718
	else
Packit Service def718
	{
Packit Service def718
		_json_c_set_last_err("json_c_set_option: invalid global_or_thread value: %d\n", global_or_thread);
Packit Service def718
		return -1;
Packit Service def718
	}
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
static int json_object_double_to_json_string_format(struct json_object* jso,
Packit Service def718
						    struct printbuf *pb,
Packit Service def718
						    int level,
Packit Service def718
						    int flags,
Packit Service def718
						    const char *format)
Packit Service def718
{
Packit Service def718
	char buf[128], *p, *q;
Packit Service def718
	int size;
Packit Service def718
	/* Although JSON RFC does not support
Packit Service def718
	NaN or Infinity as numeric values
Packit Service def718
	ECMA 262 section 9.8.1 defines
Packit Service def718
	how to handle these cases as strings */
Packit Service def718
	if (isnan(jso->o.c_double))
Packit Service def718
	{
Packit Service def718
		size = snprintf(buf, sizeof(buf), "NaN");
Packit Service def718
	}
Packit Service def718
	else if (isinf(jso->o.c_double))
Packit Service def718
	{
Packit Service def718
		if(jso->o.c_double > 0)
Packit Service def718
			size = snprintf(buf, sizeof(buf), "Infinity");
Packit Service def718
		else
Packit Service def718
			size = snprintf(buf, sizeof(buf), "-Infinity");
Packit Service def718
	}
Packit Service def718
	else
Packit Service def718
	{
Packit Service def718
		const char *std_format = "%.17g";
Packit Service def718
		int format_drops_decimals = 0;
Packit Service def718
Packit Service def718
		if (!format)
Packit Service def718
		{
Packit Service def718
#if defined(HAVE___THREAD)
Packit Service def718
			if (tls_serialization_float_format)
Packit Service def718
				format = tls_serialization_float_format;
Packit Service def718
			else
Packit Service def718
#endif
Packit Service def718
			if (global_serialization_float_format)
Packit Service def718
				format = global_serialization_float_format;
Packit Service def718
			else
Packit Service def718
				format = std_format;
Packit Service def718
		}
Packit Service def718
		size = snprintf(buf, sizeof(buf), format, jso->o.c_double);
Packit Service def718
Packit Service def718
		if (size < 0)
Packit Service def718
			return -1;
Packit Service def718
Packit Service def718
		p = strchr(buf, ',');
Packit Service def718
		if (p)
Packit Service def718
			*p = '.';
Packit Service def718
		else
Packit Service def718
			p = strchr(buf, '.');
Packit Service def718
Packit Service def718
		if (format == std_format || strstr(format, ".0f") == NULL)
Packit Service def718
			format_drops_decimals = 1;
Packit Service def718
Packit Service def718
		if (size < (int)sizeof(buf) - 2 &&
Packit Service def718
		    isdigit((int)buf[0]) && /* Looks like *some* kind of number */
Packit Service def718
			!p && /* Has no decimal point */
Packit Service def718
		    strchr(buf, 'e') == NULL && /* Not scientific notation */
Packit Service def718
			format_drops_decimals)
Packit Service def718
		{
Packit Service def718
			// Ensure it looks like a float, even if snprintf didn't,
Packit Service def718
			//  unless a custom format is set to omit the decimal.
Packit Service def718
			strcat(buf, ".0");
Packit Service def718
			size += 2;
Packit Service def718
		}
Packit Service def718
		if (p && (flags & JSON_C_TO_STRING_NOZERO))
Packit Service def718
		{
Packit Service def718
			/* last useful digit, always keep 1 zero */
Packit Service def718
			p++;
Packit Service def718
			for (q=p ; *q ; q++) {
Packit Service def718
				if (*q!='0') p=q;
Packit Service def718
			}
Packit Service def718
			/* drop trailing zeroes */
Packit Service def718
			*(++p) = 0;
Packit Service def718
			size = p-buf;
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
	// although unlikely, snprintf can fail
Packit Service def718
	if (size < 0)
Packit Service def718
		return -1;
Packit Service def718
Packit Service def718
	if (size >= (int)sizeof(buf))
Packit Service def718
		// The standard formats are guaranteed not to overrun the buffer,
Packit Service def718
		// but if a custom one happens to do so, just silently truncate.
Packit Service def718
		size = sizeof(buf) - 1;
Packit Service def718
	printbuf_memappend(pb, buf, size);
Packit Service def718
	return size;
Packit Service def718
}
Packit Service def718
Packit Service def718
static int json_object_double_to_json_string_default(struct json_object* jso,
Packit Service def718
						     struct printbuf *pb,
Packit Service def718
						     int level,
Packit Service def718
						     int flags)
Packit Service def718
{
Packit Service def718
	return json_object_double_to_json_string_format(jso, pb, level, flags,
Packit Service def718
							NULL);
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_double_to_json_string(struct json_object* jso,
Packit Service def718
				      struct printbuf *pb,
Packit Service def718
				      int level,
Packit Service def718
				      int flags)
Packit Service def718
{
Packit Service def718
	return json_object_double_to_json_string_format(jso, pb, level, flags,
Packit Service def718
							(const char *)jso->_userdata);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_double(double d)
Packit Service def718
{
Packit Service def718
	struct json_object *jso = json_object_new(json_type_double);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_to_json_string = &json_object_double_to_json_string_default;
Packit Service def718
	jso->o.c_double = d;
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_double_s(double d, const char *ds)
Packit Service def718
{
Packit Service def718
	char *new_ds;
Packit Service def718
	struct json_object *jso = json_object_new_double(d);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
Packit Service def718
	new_ds = strdup(ds);
Packit Service def718
	if (!new_ds)
Packit Service def718
	{
Packit Service def718
		json_object_generic_delete(jso);
Packit Service def718
		errno = ENOMEM;
Packit Service def718
		return NULL;
Packit Service def718
	}
Packit Service def718
	json_object_set_serializer(jso, json_object_userdata_to_json_string,
Packit Service def718
	    new_ds, json_object_free_userdata);
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_userdata_to_json_string(struct json_object *jso,
Packit Service def718
	struct printbuf *pb, int level, int flags)
Packit Service def718
{
Packit Service def718
	int userdata_len = strlen((const char *)jso->_userdata);
Packit Service def718
	printbuf_memappend(pb, (const char *)jso->_userdata, userdata_len);
Packit Service def718
	return userdata_len;
Packit Service def718
}
Packit Service def718
Packit Service def718
void json_object_free_userdata(struct json_object *jso, void *userdata)
Packit Service def718
{
Packit Service def718
	free(userdata);
Packit Service def718
}
Packit Service def718
Packit Service def718
double json_object_get_double(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
  double cdouble;
Packit Service def718
  char *errPtr = NULL;
Packit Service def718
Packit Service def718
  if(!jso) return 0.0;
Packit Service def718
  switch(jso->o_type) {
Packit Service def718
  case json_type_double:
Packit Service def718
    return jso->o.c_double;
Packit Service def718
  case json_type_int:
Packit Service def718
    return jso->o.c_int64;
Packit Service def718
  case json_type_boolean:
Packit Service def718
    return jso->o.c_boolean;
Packit Service def718
  case json_type_string:
Packit Service def718
    errno = 0;
Packit Service def718
    cdouble = strtod(get_string_component(jso), &errPtr);
Packit Service def718
Packit Service def718
    /* if conversion stopped at the first character, return 0.0 */
Packit Service def718
    if (errPtr == get_string_component(jso))
Packit Service def718
        return 0.0;
Packit Service def718
Packit Service def718
    /*
Packit Service def718
     * Check that the conversion terminated on something sensible
Packit Service def718
     *
Packit Service def718
     * For example, { "pay" : 123AB } would parse as 123.
Packit Service def718
     */
Packit Service def718
    if (*errPtr != '\0')
Packit Service def718
        return 0.0;
Packit Service def718
Packit Service def718
    /*
Packit Service def718
     * If strtod encounters a string which would exceed the
Packit Service def718
     * capacity of a double, it returns +/- HUGE_VAL and sets
Packit Service def718
     * errno to ERANGE. But +/- HUGE_VAL is also a valid result
Packit Service def718
     * from a conversion, so we need to check errno.
Packit Service def718
     *
Packit Service def718
     * Underflow also sets errno to ERANGE, but it returns 0 in
Packit Service def718
     * that case, which is what we will return anyway.
Packit Service def718
     *
Packit Service def718
     * See CERT guideline ERR30-C
Packit Service def718
     */
Packit Service def718
    if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) &&
Packit Service def718
        (ERANGE == errno))
Packit Service def718
            cdouble = 0.0;
Packit Service def718
    return cdouble;
Packit Service def718
  default:
Packit Service def718
    return 0.0;
Packit Service def718
  }
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_set_double(struct json_object *jso,double new_value){
Packit Service def718
	if (!jso || jso->o_type!=json_type_double)
Packit Service def718
		return 0;
Packit Service def718
	jso->o.c_double=new_value;
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
/* json_object_string */
Packit Service def718
Packit Service def718
static int json_object_string_to_json_string(struct json_object* jso,
Packit Service def718
					     struct printbuf *pb,
Packit Service def718
					     int level,
Packit Service def718
					     int flags)
Packit Service def718
{
Packit Service def718
	printbuf_strappend(pb, "\"");
Packit Service def718
	json_escape_str(pb, get_string_component(jso), jso->o.c_string.len, flags);
Packit Service def718
	printbuf_strappend(pb, "\"");
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
static void json_object_string_delete(struct json_object* jso)
Packit Service def718
{
Packit Service def718
	if(jso->o.c_string.len >= LEN_DIRECT_STRING_DATA)
Packit Service def718
		free(jso->o.c_string.str.ptr);
Packit Service def718
	json_object_generic_delete(jso);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_string(const char *s)
Packit Service def718
{
Packit Service def718
	struct json_object *jso = json_object_new(json_type_string);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_delete = &json_object_string_delete;
Packit Service def718
	jso->_to_json_string = &json_object_string_to_json_string;
Packit Service def718
	jso->o.c_string.len = strlen(s);
Packit Service def718
	if(jso->o.c_string.len < LEN_DIRECT_STRING_DATA) {
Packit Service def718
		memcpy(jso->o.c_string.str.data, s, jso->o.c_string.len);
Packit Service def718
	} else {
Packit Service def718
		jso->o.c_string.str.ptr = strdup(s);
Packit Service def718
		if (!jso->o.c_string.str.ptr)
Packit Service def718
		{
Packit Service def718
			json_object_generic_delete(jso);
Packit Service def718
			errno = ENOMEM;
Packit Service def718
			return NULL;
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_string_len(const char *s, int len)
Packit Service def718
{
Packit Service def718
	char *dstbuf;
Packit Service def718
	struct json_object *jso = json_object_new(json_type_string);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_delete = &json_object_string_delete;
Packit Service def718
	jso->_to_json_string = &json_object_string_to_json_string;
Packit Service def718
	if(len < LEN_DIRECT_STRING_DATA) {
Packit Service def718
		dstbuf = jso->o.c_string.str.data;
Packit Service def718
	} else {
Packit Service def718
		jso->o.c_string.str.ptr = (char*)malloc(len + 1);
Packit Service def718
		if (!jso->o.c_string.str.ptr)
Packit Service def718
		{
Packit Service def718
			json_object_generic_delete(jso);
Packit Service def718
			errno = ENOMEM;
Packit Service def718
			return NULL;
Packit Service def718
		}
Packit Service def718
		dstbuf = jso->o.c_string.str.ptr;
Packit Service def718
	}
Packit Service def718
	memcpy(dstbuf, (const void *)s, len);
Packit Service def718
	dstbuf[len] = '\0';
Packit Service def718
	jso->o.c_string.len = len;
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
const char* json_object_get_string(struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	switch(jso->o_type)
Packit Service def718
	{
Packit Service def718
	case json_type_string:
Packit Service def718
		return get_string_component(jso);
Packit Service def718
	default:
Packit Service def718
		return json_object_to_json_string(jso);
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_get_string_len(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if (!jso)
Packit Service def718
		return 0;
Packit Service def718
	switch(jso->o_type)
Packit Service def718
	{
Packit Service def718
	case json_type_string:
Packit Service def718
		return jso->o.c_string.len;
Packit Service def718
	default:
Packit Service def718
		return 0;
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_set_string(json_object* jso, const char* s) {
Packit Service def718
	return json_object_set_string_len(jso, s, (int)(strlen(s)));
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_set_string_len(json_object* jso, const char* s, int len){
Packit Service def718
	char *dstbuf; 
Packit Service def718
	if (jso==NULL || jso->o_type!=json_type_string) return 0; 	
Packit Service def718
	if (len
Packit Service def718
		dstbuf=jso->o.c_string.str.data;
Packit Service def718
		if (jso->o.c_string.len>=LEN_DIRECT_STRING_DATA) free(jso->o.c_string.str.ptr); 
Packit Service def718
	} else {
Packit Service def718
		dstbuf=(char *)malloc(len+1);
Packit Service def718
		if (dstbuf==NULL) return 0;
Packit Service def718
		if (jso->o.c_string.len>=LEN_DIRECT_STRING_DATA) free(jso->o.c_string.str.ptr);
Packit Service def718
		jso->o.c_string.str.ptr=dstbuf;
Packit Service def718
	}
Packit Service def718
	jso->o.c_string.len=len;
Packit Service def718
	memcpy(dstbuf, (const void *)s, len);
Packit Service def718
	dstbuf[len] = '\0';
Packit Service def718
	return 1; 
Packit Service def718
}
Packit Service def718
Packit Service def718
/* json_object_array */
Packit Service def718
Packit Service def718
static int json_object_array_to_json_string(struct json_object* jso,
Packit Service def718
                                            struct printbuf *pb,
Packit Service def718
                                            int level,
Packit Service def718
                                            int flags)
Packit Service def718
{
Packit Service def718
	int had_children = 0;
Packit Service def718
	size_t ii;
Packit Service def718
Packit Service def718
	printbuf_strappend(pb, "[");
Packit Service def718
	if (flags & JSON_C_TO_STRING_PRETTY)
Packit Service def718
		printbuf_strappend(pb, "\n");
Packit Service def718
	for(ii=0; ii < json_object_array_length(jso); ii++)
Packit Service def718
	{
Packit Service def718
		struct json_object *val;
Packit Service def718
		if (had_children)
Packit Service def718
		{
Packit Service def718
			printbuf_strappend(pb, ",");
Packit Service def718
			if (flags & JSON_C_TO_STRING_PRETTY)
Packit Service def718
				printbuf_strappend(pb, "\n");
Packit Service def718
		}
Packit Service def718
		had_children = 1;
Packit Service def718
		if (flags & JSON_C_TO_STRING_SPACED)
Packit Service def718
			printbuf_strappend(pb, " ");
Packit Service def718
		indent(pb, level + 1, flags);
Packit Service def718
		val = json_object_array_get_idx(jso, ii);
Packit Service def718
		if(val == NULL)
Packit Service def718
			printbuf_strappend(pb, "null");
Packit Service def718
		else
Packit Service def718
			if (val->_to_json_string(val, pb, level+1, flags) < 0)
Packit Service def718
				return -1;
Packit Service def718
	}
Packit Service def718
	if (flags & JSON_C_TO_STRING_PRETTY)
Packit Service def718
	{
Packit Service def718
		if (had_children)
Packit Service def718
			printbuf_strappend(pb, "\n");
Packit Service def718
		indent(pb,level,flags);
Packit Service def718
	}
Packit Service def718
Packit Service def718
	if (flags & JSON_C_TO_STRING_SPACED)
Packit Service def718
		return printbuf_strappend(pb, " ]");
Packit Service def718
	return printbuf_strappend(pb, "]");
Packit Service def718
}
Packit Service def718
Packit Service def718
static void json_object_array_entry_free(void *data)
Packit Service def718
{
Packit Service def718
	json_object_put((struct json_object*)data);
Packit Service def718
}
Packit Service def718
Packit Service def718
static void json_object_array_delete(struct json_object* jso)
Packit Service def718
{
Packit Service def718
	array_list_free(jso->o.c_array);
Packit Service def718
	json_object_generic_delete(jso);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_new_array(void)
Packit Service def718
{
Packit Service def718
	struct json_object *jso = json_object_new(json_type_array);
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	jso->_delete = &json_object_array_delete;
Packit Service def718
	jso->_to_json_string = &json_object_array_to_json_string;
Packit Service def718
	jso->o.c_array = array_list_new(&json_object_array_entry_free);
Packit Service def718
        if(jso->o.c_array == NULL)
Packit Service def718
	{
Packit Service def718
	    free(jso);
Packit Service def718
	    return NULL;
Packit Service def718
	}
Packit Service def718
	return jso;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct array_list* json_object_get_array(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	if (!jso)
Packit Service def718
		return NULL;
Packit Service def718
	switch(jso->o_type)
Packit Service def718
	{
Packit Service def718
	case json_type_array:
Packit Service def718
		return jso->o.c_array;
Packit Service def718
	default:
Packit Service def718
		return NULL;
Packit Service def718
	}
Packit Service def718
}
Packit Service def718
Packit Service def718
void json_object_array_sort(struct json_object *jso,
Packit Service def718
			    int(*sort_fn)(const void *, const void *))
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_array);
Packit Service def718
	array_list_sort(jso->o.c_array, sort_fn);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_array_bsearch(
Packit Service def718
		const struct json_object *key,
Packit Service def718
		const struct json_object *jso,
Packit Service def718
		int (*sort_fn)(const void *, const void *))
Packit Service def718
{
Packit Service def718
	struct json_object **result;
Packit Service def718
Packit Service def718
	assert(json_object_get_type(jso) == json_type_array);
Packit Service def718
	result = (struct json_object **)array_list_bsearch(
Packit Service def718
			(const void **)(void *)&key, jso->o.c_array, sort_fn);
Packit Service def718
Packit Service def718
	if (!result)
Packit Service def718
		return NULL;
Packit Service def718
	return *result;
Packit Service def718
}
Packit Service def718
Packit Service def718
size_t json_object_array_length(const struct json_object *jso)
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_array);
Packit Service def718
	return array_list_length(jso->o.c_array);
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_array_add(struct json_object *jso,struct json_object *val)
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_array);
Packit Service def718
	return array_list_add(jso->o.c_array, val);
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_array_put_idx(struct json_object *jso, size_t idx,
Packit Service def718
			      struct json_object *val)
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_array);
Packit Service def718
	return array_list_put_idx(jso->o.c_array, idx, val);
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_array_del_idx(struct json_object *jso, size_t idx, size_t count)
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_array);
Packit Service def718
	return array_list_del_idx(jso->o.c_array, idx, count);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_object_array_get_idx(const struct json_object *jso,
Packit Service def718
					      size_t idx)
Packit Service def718
{
Packit Service def718
	assert(json_object_get_type(jso) == json_type_array);
Packit Service def718
	return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
Packit Service def718
}
Packit Service def718
Packit Service def718
static int json_array_equal(struct json_object* jso1,
Packit Service def718
			    struct json_object* jso2)
Packit Service def718
{
Packit Service def718
	size_t len, i;
Packit Service def718
Packit Service def718
	len = json_object_array_length(jso1);
Packit Service def718
	if (len != json_object_array_length(jso2))
Packit Service def718
		return 0;
Packit Service def718
Packit Service def718
	for (i = 0; i < len; i++) {
Packit Service def718
		if (!json_object_equal(json_object_array_get_idx(jso1, i),
Packit Service def718
				       json_object_array_get_idx(jso2, i)))
Packit Service def718
			return 0;
Packit Service def718
	}
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
static int json_object_all_values_equal(struct json_object* jso1,
Packit Service def718
					struct json_object* jso2)
Packit Service def718
{
Packit Service def718
	struct json_object_iter iter;
Packit Service def718
	struct json_object *sub;
Packit Service def718
Packit Service def718
	assert(json_object_get_type(jso1) == json_type_object);
Packit Service def718
	assert(json_object_get_type(jso2) == json_type_object);
Packit Service def718
	/* Iterate over jso1 keys and see if they exist and are equal in jso2 */
Packit Service def718
        json_object_object_foreachC(jso1, iter) {
Packit Service def718
		if (!lh_table_lookup_ex(jso2->o.c_object, (void*)iter.key,
Packit Service def718
					(void**)(void *)&sub))
Packit Service def718
			return 0;
Packit Service def718
		if (!json_object_equal(iter.val, sub))
Packit Service def718
			return 0;
Packit Service def718
        }
Packit Service def718
Packit Service def718
	/* Iterate over jso2 keys to see if any exist that are not in jso1 */
Packit Service def718
        json_object_object_foreachC(jso2, iter) {
Packit Service def718
		if (!lh_table_lookup_ex(jso1->o.c_object, (void*)iter.key,
Packit Service def718
					(void**)(void *)&sub))
Packit Service def718
			return 0;
Packit Service def718
        }
Packit Service def718
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_equal(struct json_object* jso1, struct json_object* jso2)
Packit Service def718
{
Packit Service def718
	if (jso1 == jso2)
Packit Service def718
		return 1;
Packit Service def718
Packit Service def718
	if (!jso1 || !jso2)
Packit Service def718
		return 0;
Packit Service def718
Packit Service def718
	if (jso1->o_type != jso2->o_type)
Packit Service def718
		return 0;
Packit Service def718
Packit Service def718
	switch(jso1->o_type) {
Packit Service def718
		case json_type_boolean:
Packit Service def718
			return (jso1->o.c_boolean == jso2->o.c_boolean);
Packit Service def718
Packit Service def718
		case json_type_double:
Packit Service def718
			return (jso1->o.c_double == jso2->o.c_double);
Packit Service def718
Packit Service def718
		case json_type_int:
Packit Service def718
			return (jso1->o.c_int64 == jso2->o.c_int64);
Packit Service def718
Packit Service def718
		case json_type_string:
Packit Service def718
			return (jso1->o.c_string.len == jso2->o.c_string.len &&
Packit Service def718
				memcmp(get_string_component(jso1),
Packit Service def718
				       get_string_component(jso2),
Packit Service def718
				       jso1->o.c_string.len) == 0);
Packit Service def718
Packit Service def718
		case json_type_object:
Packit Service def718
			return json_object_all_values_equal(jso1, jso2);
Packit Service def718
Packit Service def718
		case json_type_array:
Packit Service def718
			return json_array_equal(jso1, jso2);
Packit Service def718
Packit Service def718
		case json_type_null:
Packit Service def718
			return 1;
Packit Service def718
	};
Packit Service def718
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
static int json_object_copy_serializer_data(struct json_object *src, struct json_object *dst)
Packit Service def718
{
Packit Service def718
	if (!src->_userdata && !src->_user_delete)
Packit Service def718
		return 0;
Packit Service def718
Packit Service def718
	if (dst->_to_json_string == json_object_userdata_to_json_string)
Packit Service def718
	{
Packit Service def718
		dst->_userdata = strdup(src->_userdata);
Packit Service def718
	}
Packit Service def718
	// else if ... other supported serializers ...
Packit Service def718
	else
Packit Service def718
	{
Packit Service def718
		_json_c_set_last_err("json_object_deep_copy: unable to copy unknown serializer data: %p\n", dst->_to_json_string);
Packit Service def718
		return -1;
Packit Service def718
	}
Packit Service def718
	dst->_user_delete = src->_user_delete;
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/**
Packit Service def718
 * The default shallow copy implementation.  Simply creates a new object of the same
Packit Service def718
 * type but does *not* copy over _userdata nor retain any custom serializer.
Packit Service def718
 * If custom serializers are in use, json_object_deep_copy() must be passed a shallow copy
Packit Service def718
 * implementation that is aware of how to copy them.
Packit Service def718
 *
Packit Service def718
 * This always returns -1 or 1.  It will never return 2 since it does not copy the serializer.
Packit Service def718
 */
Packit Service def718
int json_c_shallow_copy_default(json_object *src, json_object *parent, const char *key, size_t index, json_object **dst)
Packit Service def718
{
Packit Service def718
	switch (src->o_type) {
Packit Service def718
	case json_type_boolean:
Packit Service def718
		*dst = json_object_new_boolean(src->o.c_boolean);
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	case json_type_double:
Packit Service def718
		*dst = json_object_new_double(src->o.c_double);
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	case json_type_int:
Packit Service def718
		*dst = json_object_new_int64(src->o.c_int64);
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	case json_type_string:
Packit Service def718
		*dst = json_object_new_string(get_string_component(src));
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	case json_type_object:
Packit Service def718
		*dst = json_object_new_object();
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	case json_type_array:
Packit Service def718
		*dst = json_object_new_array();
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	default:
Packit Service def718
		errno = EINVAL;
Packit Service def718
		return -1;
Packit Service def718
	}
Packit Service def718
Packit Service def718
	if (!*dst) {
Packit Service def718
		errno = ENOMEM;
Packit Service def718
		return -1;
Packit Service def718
	}
Packit Service def718
	(*dst)->_to_json_string = src->_to_json_string;
Packit Service def718
	// _userdata and _user_delete are copied later
Packit Service def718
	return 1;
Packit Service def718
}
Packit Service def718
Packit Service def718
/*
Packit Service def718
 * The actual guts of json_object_deep_copy(), with a few additional args
Packit Service def718
 * needed so we can keep track of where we are within the object tree.
Packit Service def718
 *
Packit Service def718
 * Note: caller is responsible for freeing *dst if this fails and returns -1.
Packit Service def718
 */
Packit Service def718
static int json_object_deep_copy_recursive(struct json_object *src, struct json_object *parent, const char *key_in_parent, size_t index_in_parent, struct json_object **dst, json_c_shallow_copy_fn *shallow_copy)
Packit Service def718
{
Packit Service def718
	struct json_object_iter iter;
Packit Service def718
	size_t src_array_len, ii;
Packit Service def718
Packit Service def718
	int shallow_copy_rc = 0;
Packit Service def718
	shallow_copy_rc = shallow_copy(src, parent, key_in_parent, index_in_parent, dst);
Packit Service def718
	/* -1=error, 1=object created ok, 2=userdata set */
Packit Service def718
	if (shallow_copy_rc < 1)
Packit Service def718
	{
Packit Service def718
		errno = EINVAL;
Packit Service def718
		return -1;
Packit Service def718
	}
Packit Service def718
	assert(*dst != NULL);
Packit Service def718
Packit Service def718
	switch (src->o_type) {
Packit Service def718
	case json_type_object:
Packit Service def718
		json_object_object_foreachC(src, iter) {
Packit Service def718
			struct json_object *jso = NULL;
Packit Service def718
			/* This handles the `json_type_null` case */
Packit Service def718
			if (!iter.val)
Packit Service def718
				jso = NULL;
Packit Service def718
			else if (json_object_deep_copy_recursive(iter.val, src, iter.key, -1, &jso, shallow_copy) < 0)
Packit Service def718
			{
Packit Service def718
				json_object_put(jso);
Packit Service def718
				return -1;
Packit Service def718
			}
Packit Service def718
Packit Service def718
			if (json_object_object_add(*dst, iter.key, jso) < 0)
Packit Service def718
			{
Packit Service def718
				json_object_put(jso);
Packit Service def718
				return -1;
Packit Service def718
			}
Packit Service def718
		}
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	case json_type_array:
Packit Service def718
		src_array_len = json_object_array_length(src);
Packit Service def718
		for (ii = 0; ii < src_array_len; ii++) {
Packit Service def718
			struct json_object *jso = NULL;
Packit Service def718
			struct json_object *jso1 = json_object_array_get_idx(src, ii);
Packit Service def718
			/* This handles the `json_type_null` case */
Packit Service def718
			if (!jso1)
Packit Service def718
				jso = NULL;
Packit Service def718
			else if (json_object_deep_copy_recursive(jso1, src, NULL, ii, &jso, shallow_copy) < 0)
Packit Service def718
			{
Packit Service def718
				json_object_put(jso);
Packit Service def718
				return -1;
Packit Service def718
			}
Packit Service def718
Packit Service def718
			if (json_object_array_add(*dst, jso) < 0)
Packit Service def718
			{
Packit Service def718
				json_object_put(jso);
Packit Service def718
				return -1;
Packit Service def718
			}
Packit Service def718
		}
Packit Service def718
		break;
Packit Service def718
Packit Service def718
	default:
Packit Service def718
		break;
Packit Service def718
		/* else, nothing to do, shallow_copy already did. */
Packit Service def718
	}
Packit Service def718
Packit Service def718
	if (shallow_copy_rc != 2)
Packit Service def718
		return json_object_copy_serializer_data(src, *dst);
Packit Service def718
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
int json_object_deep_copy(struct json_object *src, struct json_object **dst, json_c_shallow_copy_fn *shallow_copy)
Packit Service def718
{
Packit Service def718
	int rc;
Packit Service def718
Packit Service def718
	/* Check if arguments are sane ; *dst must not point to a non-NULL object */
Packit Service def718
	if (!src || !dst || *dst) {
Packit Service def718
		errno = EINVAL;
Packit Service def718
		return -1;
Packit Service def718
	}
Packit Service def718
Packit Service def718
	if (shallow_copy == NULL)
Packit Service def718
		shallow_copy = json_c_shallow_copy_default;
Packit Service def718
Packit Service def718
	rc = json_object_deep_copy_recursive(src, NULL, NULL, -1, dst, shallow_copy);
Packit Service def718
	if (rc < 0) {
Packit Service def718
		json_object_put(*dst);
Packit Service def718
		*dst = NULL;
Packit Service def718
	}
Packit Service def718
Packit Service def718
	return rc;
Packit Service def718
}
Packit Service def718