import of version 0.1
git-svn-id: http://svn.metaparadigm.com/svn/json-c/trunk@2 327403b1-1117-474d-bef2-5cb71233fd97
This commit is contained in:
40
Makefile
Normal file
40
Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
# $Id: Makefile,v 1.4 2004/07/22 01:37:44 mclark Exp $
|
||||
|
||||
CFLAGS += -g -Wall -std=gnu99 -D_GNU_SOURCE -D_REENTRANT
|
||||
LDFLAGS +=
|
||||
LDLIBS +=
|
||||
|
||||
LIB_OBJS = debug.o \
|
||||
linkhash.o \
|
||||
printbuf.o \
|
||||
arraylist.o \
|
||||
json_object.o \
|
||||
json_tokener.o
|
||||
|
||||
LIB_HDRS = debug.h \
|
||||
linkhash.h \
|
||||
printbuf.h \
|
||||
arraylist.h \
|
||||
json_object.h \
|
||||
json_tokener.h
|
||||
|
||||
TESTS = test1 test2
|
||||
|
||||
all: tests
|
||||
|
||||
tests: $(TESTS)
|
||||
test1: test1.o $(LIB_OBJS)
|
||||
test2: test2.o $(LIB_OBJS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ $(TESTS)
|
||||
|
||||
cex.o: cex.c cex.h
|
||||
debug.o: debug.c debug.h
|
||||
linkhash.o: linkhash.c linkhash.h
|
||||
arraylist.o: arraylist.c arraylist.h
|
||||
json_object.o: json_object.c $(LIB_HDRS)
|
||||
json_tokener.o: json_tokener.c $(LIB_HDRS)
|
||||
test1.o: test1.c $(LIB_HDRS)
|
||||
test2.o: test2.c $(LIB_HDRS)
|
||||
|
||||
32
README.html
Normal file
32
README.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<h2>JSON-C - A JSON implementation in C</h2>
|
||||
<p>Latest release: <a href="json-c-0.1.tar.gz">json-c-0.1.tar.gz</a></p>
|
||||
|
||||
<p>JSON-C implements a reference counting object model that allows you
|
||||
to easily construct JSON objects in C, output them as JSON formatted strings
|
||||
and parse JSON formatted strings back into the C representation of JSON
|
||||
objects.</p>
|
||||
|
||||
<p>Minimal documentation exists <a href="doc/html/json__object_8h.html">here</a>,
|
||||
Although you are probably better reading the example code in test1.c.</p>
|
||||
|
||||
<p>JSON-C currently depends on some gcc 3.0+ features so can probably only be
|
||||
compiled with gcc 3.0+. It also uses some specifc glibc functions such as
|
||||
vasprintf. Patches welcome to port to other compilers / platforms.</p>
|
||||
|
||||
<p>Please send bug reports to <a href="mailto:michael@metaparadigm.com">michael@metaparadigm.com</a></p>
|
||||
|
||||
<h3>Anonymous CVS</h3>
|
||||
<p><code># <b>export CVSROOT=:pserver:anoncvs@cvs.metaparadigm.com:/cvsroot</b><br>
|
||||
# <b>cvs login</b><br>
|
||||
Logging in to :pserver:anoncvs@cvs.metaparadigm.com:2401/cvsroot<br>
|
||||
CVS password: <enter '<b>anoncvs</b>'><br>
|
||||
# <b>cvs co json-c</b></code></p>
|
||||
|
||||
<p>Copyright Metaparadigm Pte. Ltd. 2004. <a href="mailto:michael@metaparadigm.com">Michael Clark </a></p>
|
||||
|
||||
<p>This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.</p>
|
||||
|
||||
<hr>
|
||||
94
arraylist.c
Normal file
94
arraylist.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* $Id: arraylist.c,v 1.2 2004/07/21 01:24:33 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "arraylist.h"
|
||||
|
||||
|
||||
struct array_list*
|
||||
array_list_new(array_list_free_fn *free_fn)
|
||||
{
|
||||
struct array_list *this;
|
||||
|
||||
if(!(this = calloc(1, sizeof(struct array_list)))) return NULL;
|
||||
this->size = ARRAY_LIST_DEFAULT_SIZE;
|
||||
this->length = 0;
|
||||
this->free_fn = free_fn;
|
||||
if(!(this->array = calloc(sizeof(void*), this->size))) {
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
extern void
|
||||
array_list_free(struct array_list *this)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < this->length; i++)
|
||||
if(this->array[i]) this->free_fn(this->array[i]);
|
||||
free(this->array);
|
||||
free(this);
|
||||
}
|
||||
|
||||
void*
|
||||
array_list_get_idx(struct array_list *this, int i)
|
||||
{
|
||||
if(i >= this->length) return NULL;
|
||||
return this->array[i];
|
||||
}
|
||||
|
||||
static int array_list_expand_internal(struct array_list *this, int max)
|
||||
{
|
||||
void *t;
|
||||
int new_size;
|
||||
|
||||
if(max < this->size) return 0;
|
||||
new_size = max(this->size << 1, max);
|
||||
if(!(t = realloc(this->array, new_size*sizeof(void*)))) return -1;
|
||||
this->array = t;
|
||||
bzero(this->array + this->size, (new_size-this->size)*sizeof(void*));
|
||||
this->size = new_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
array_list_put_idx(struct array_list *this, int idx, void *data)
|
||||
{
|
||||
if(array_list_expand_internal(this, idx)) return -1;
|
||||
if(this->array[idx]) this->free_fn(this->array[idx]);
|
||||
this->array[idx] = data;
|
||||
if(this->length <= idx) this->length = idx + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
array_list_add(struct array_list *this, void *data)
|
||||
{
|
||||
return array_list_put_idx(this, this->length, data);
|
||||
}
|
||||
|
||||
int
|
||||
array_list_length(struct array_list *this)
|
||||
{
|
||||
return this->length;
|
||||
}
|
||||
52
arraylist.h
Normal file
52
arraylist.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* $Id: arraylist.h,v 1.2 2004/07/21 01:24:33 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _arraylist_h_
|
||||
#define _arraylist_h_
|
||||
|
||||
#define ARRAY_LIST_DEFAULT_SIZE 32
|
||||
|
||||
typedef void (array_list_free_fn) (void *data);
|
||||
|
||||
struct array_list
|
||||
{
|
||||
void **array;
|
||||
int length;
|
||||
int size;
|
||||
array_list_free_fn *free_fn;
|
||||
};
|
||||
|
||||
extern struct array_list*
|
||||
array_list_new(array_list_free_fn *free_fn);
|
||||
|
||||
extern void
|
||||
array_list_free(struct array_list *this);
|
||||
|
||||
extern void*
|
||||
array_list_get_idx(struct array_list *this, int i);
|
||||
|
||||
extern int
|
||||
array_list_put_idx(struct array_list *this, int i, void *data);
|
||||
|
||||
extern int
|
||||
array_list_add(struct array_list *this, void *data);
|
||||
|
||||
extern int
|
||||
array_list_length(struct array_list *this);
|
||||
|
||||
#endif
|
||||
38
bits.h
Normal file
38
bits.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* $Id: bits.h,v 1.3 2004/07/21 10:10:22 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _bits_h_
|
||||
#define _bits_h_
|
||||
|
||||
#define min(x,y) ({ \
|
||||
typeof(x) _x = (x); \
|
||||
typeof(y) _y = (y); \
|
||||
(void) (&_x == &_y); \
|
||||
_x < _y ? _x : _y; })
|
||||
|
||||
#define max(x,y) ({ \
|
||||
typeof(x) _x = (x); \
|
||||
typeof(y) _y = (y); \
|
||||
(void) (&_x == &_y); \
|
||||
_x > _y ? _x : _y; })
|
||||
|
||||
#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
|
||||
#define error_ptr(error) ((void*)error)
|
||||
#define is_error(ptr) ((unsigned long)ptr > (unsigned long)-4000L)
|
||||
|
||||
#endif
|
||||
75
debug.c
Normal file
75
debug.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* $Id: debug.c,v 1.3 2004/08/07 03:11:38 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
static int _syslog = 0;
|
||||
static int _debug = 0;
|
||||
|
||||
void mc_set_debug(int debug) { _debug = debug; }
|
||||
int mc_get_debug() { return _debug; }
|
||||
|
||||
extern void mc_set_syslog(int syslog)
|
||||
{
|
||||
_syslog = syslog;
|
||||
}
|
||||
|
||||
void mc_abort(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
if(_syslog) vsyslog(LOG_ERR, msg, ap);
|
||||
else vprintf(msg, ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void mc_debug(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
if(_debug) {
|
||||
va_start(ap, msg);
|
||||
if(_syslog) vsyslog(LOG_DEBUG, msg, ap);
|
||||
else vprintf(msg, ap);
|
||||
}
|
||||
}
|
||||
|
||||
void mc_error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
if(_syslog) vsyslog(LOG_ERR, msg, ap);
|
||||
else vfprintf(stderr, msg, ap);
|
||||
}
|
||||
|
||||
void mc_info(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
if(_syslog) vsyslog(LOG_INFO, msg, ap);
|
||||
else vfprintf(stderr, msg, ap);
|
||||
}
|
||||
33
debug.h
Normal file
33
debug.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* $Id: debug.h,v 1.2 2004/07/21 01:24:33 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
#define errstr strerror(errno)
|
||||
|
||||
extern void mc_set_debug(int debug);
|
||||
extern int mc_get_debug();
|
||||
|
||||
extern void mc_set_syslog(int syslog);
|
||||
extern void mc_abort(const char *msg, ...);
|
||||
extern void mc_debug(const char *msg, ...);
|
||||
extern void mc_error(const char *msg, ...);
|
||||
extern void mc_info(const char *msg, ...);
|
||||
|
||||
#endif
|
||||
30
json.h
Normal file
30
json.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* $Id: json.h,v 1.4 2004/08/07 03:13:52 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _json_h_
|
||||
#define _json_h_
|
||||
|
||||
#include "bits.h"
|
||||
#include "debug.h"
|
||||
#include "linkhash.h"
|
||||
#include "arraylist.h"
|
||||
#include "json_util.h"
|
||||
#include "json_object.h"
|
||||
#include "json_tokener.h"
|
||||
|
||||
#endif
|
||||
493
json_object.c
Normal file
493
json_object.c
Normal file
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* $Id: json_object.c,v 1.10 2004/08/07 03:12:43 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "printbuf.h"
|
||||
#include "linkhash.h"
|
||||
#include "arraylist.h"
|
||||
#include "json_object.h"
|
||||
#include "json_object_private.h"
|
||||
|
||||
|
||||
/* #define REFCOUNT_DEBUG */
|
||||
|
||||
char *json_number_chars = "0123456789.+-e";
|
||||
char *json_hex_chars = "0123456789abcdef";
|
||||
|
||||
#ifdef REFCOUNT_DEBUG
|
||||
static char* json_type_name[] = {
|
||||
"null",
|
||||
"boolean",
|
||||
"double",
|
||||
"int",
|
||||
"object",
|
||||
"array",
|
||||
"string",
|
||||
};
|
||||
#endif
|
||||
|
||||
static void json_object_generic_delete(struct json_object* this);
|
||||
static struct json_object* json_object_new(enum json_type o_type);
|
||||
|
||||
|
||||
/* ref count debugging */
|
||||
|
||||
#ifdef REFCOUNT_DEBUG
|
||||
|
||||
static struct lh_table *json_object_table;
|
||||
|
||||
static void json_object_init() __attribute__ ((constructor));
|
||||
static void json_object_init() {
|
||||
mc_debug("json_object_init: creating object table\n");
|
||||
json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
|
||||
}
|
||||
|
||||
static void json_object_fini() __attribute__ ((destructor));
|
||||
static void json_object_fini() {
|
||||
struct lh_entry *ent;
|
||||
if(mc_get_debug() && json_object_table->count) {
|
||||
mc_debug("json_object_fini: %d referenced objects at exit\n",
|
||||
json_object_table->count);
|
||||
lh_foreach(json_object_table, ent) {
|
||||
struct json_object* obj = (struct json_object*)ent->v;
|
||||
mc_debug("\t%s:%p\n", json_type_name[obj->o_type], obj);
|
||||
}
|
||||
}
|
||||
mc_debug("json_object_fini: freeing object table\n");
|
||||
lh_table_free(json_object_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* string escaping */
|
||||
|
||||
static int json_escape_str(struct printbuf *pb, char *str)
|
||||
{
|
||||
int pos = 0, start_offset = 0;
|
||||
char c;
|
||||
do {
|
||||
c = str[pos];
|
||||
switch(c) {
|
||||
case '\b':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
if(pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
if(c == '\b') printbuf_memappend(pb, "\\b", 2);
|
||||
else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
|
||||
else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
|
||||
else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
|
||||
start_offset = ++pos;
|
||||
break;
|
||||
default:
|
||||
if(c && c < ' ') {
|
||||
if(pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
sprintbuf(pb, "\\u00%c%c",
|
||||
json_hex_chars[c >> 4],
|
||||
json_hex_chars[c & 0xf]);
|
||||
start_offset = ++pos;
|
||||
} else if(c) pos++;
|
||||
}
|
||||
} while(c);
|
||||
if(pos - start_offset > 0)
|
||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* reference counting */
|
||||
|
||||
extern struct json_object* json_object_get(struct json_object *this)
|
||||
{
|
||||
if(this) {
|
||||
this->_ref_count++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
extern void json_object_put(struct json_object *this)
|
||||
{
|
||||
if(this) {
|
||||
this->_ref_count--;
|
||||
if(!this->_ref_count) this->_delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* generic object construction and destruction parts */
|
||||
|
||||
static void json_object_generic_delete(struct json_object* this)
|
||||
{
|
||||
#ifdef REFCOUNT_DEBUG
|
||||
mc_debug("json_object_delete_%s: %p\n",
|
||||
json_type_name[this->o_type], this);
|
||||
lh_table_delete(json_object_table, this);
|
||||
#endif
|
||||
printbuf_free(this->_pb);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static struct json_object* json_object_new(enum json_type o_type)
|
||||
{
|
||||
struct json_object *this = calloc(sizeof(struct json_object), 1);
|
||||
if(!this) return NULL;
|
||||
this->o_type = o_type;
|
||||
this->_ref_count = 1;
|
||||
this->_delete = &json_object_generic_delete;
|
||||
#ifdef REFCOUNT_DEBUG
|
||||
lh_table_insert(json_object_table, this, this);
|
||||
mc_debug("json_object_new_%s: %p\n", json_type_name[this->o_type], this);
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/* type checking functions */
|
||||
|
||||
int json_object_is_type(struct json_object *this, enum json_type type)
|
||||
{
|
||||
return (this->o_type == type);
|
||||
}
|
||||
|
||||
enum json_type json_object_get_type(struct json_object *this)
|
||||
{
|
||||
return this->o_type;
|
||||
}
|
||||
|
||||
|
||||
/* json_object_to_json_string */
|
||||
|
||||
char* json_object_to_json_string(struct json_object *this)
|
||||
{
|
||||
if(!this) return "null";
|
||||
if(!this->_pb) {
|
||||
if(!(this->_pb = printbuf_new())) return NULL;
|
||||
} else {
|
||||
printbuf_reset(this->_pb);
|
||||
}
|
||||
if(this->_to_json_string(this, this->_pb) < 0) return NULL;
|
||||
return this->_pb->buf;
|
||||
}
|
||||
|
||||
|
||||
/* json_object_object */
|
||||
|
||||
static int json_object_object_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
{
|
||||
int i=0;
|
||||
sprintbuf(pb, "{");
|
||||
json_object_object_foreach(this, key, val) {
|
||||
if(i) sprintbuf(pb, ",");
|
||||
sprintbuf(pb, " \"");
|
||||
json_escape_str(pb, key);
|
||||
sprintbuf(pb, "\": ");
|
||||
if(val == NULL) sprintbuf(pb, "null");
|
||||
else val->_to_json_string(val, pb);
|
||||
i++;
|
||||
}
|
||||
return sprintbuf(pb, " }");
|
||||
}
|
||||
|
||||
static void json_object_lh_entry_free(struct lh_entry *ent)
|
||||
{
|
||||
free(ent->k);
|
||||
json_object_put((struct json_object*)ent->v);
|
||||
}
|
||||
|
||||
static void json_object_object_delete(struct json_object* this)
|
||||
{
|
||||
lh_table_free(this->o.c_object);
|
||||
json_object_generic_delete(this);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_object()
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_object);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_object_delete;
|
||||
this->_to_json_string = &json_object_object_to_json_string;
|
||||
this->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTIRES,
|
||||
NULL, &json_object_lh_entry_free);
|
||||
return this;
|
||||
}
|
||||
|
||||
struct lh_table* json_object_get_object(struct json_object *this)
|
||||
{
|
||||
if(!this) return NULL;
|
||||
switch(this->o_type) {
|
||||
case json_type_object:
|
||||
return this->o.c_object;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void json_object_object_add(struct json_object* this, char *key,
|
||||
struct json_object *val)
|
||||
{
|
||||
lh_table_delete(this->o.c_object, key);
|
||||
lh_table_insert(this->o.c_object, strdup(key), val);
|
||||
}
|
||||
|
||||
struct json_object* json_object_object_get(struct json_object* this, char *key)
|
||||
{
|
||||
return (struct json_object*) lh_table_lookup(this->o.c_object, key);
|
||||
}
|
||||
|
||||
void json_object_object_del(struct json_object* this, char *key)
|
||||
{
|
||||
lh_table_delete(this->o.c_object, key);
|
||||
}
|
||||
|
||||
|
||||
/* json_object_boolean */
|
||||
|
||||
static int json_object_boolean_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
{
|
||||
if(this->o.c_boolean) return sprintbuf(pb, "true");
|
||||
else return sprintbuf(pb, "false");
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_boolean(boolean b)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_boolean);
|
||||
if(!this) return NULL;
|
||||
this->_to_json_string = &json_object_boolean_to_json_string;
|
||||
this->o.c_boolean = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean json_object_get_boolean(struct json_object *this)
|
||||
{
|
||||
if(!this) return FALSE;
|
||||
switch(this->o_type) {
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_int:
|
||||
return (this->o.c_int != 0);
|
||||
case json_type_double:
|
||||
return (this->o.c_double != 0);
|
||||
case json_type_string:
|
||||
if(strlen(this->o.c_string)) return TRUE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_int */
|
||||
|
||||
static int json_object_int_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
{
|
||||
return sprintbuf(pb, "%d", this->o.c_int);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_int(int i)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_int);
|
||||
if(!this) return NULL;
|
||||
this->_to_json_string = &json_object_int_to_json_string;
|
||||
this->o.c_int = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
int json_object_get_int(struct json_object *this)
|
||||
{
|
||||
int cint;
|
||||
|
||||
if(!this) return 0;
|
||||
switch(this->o_type) {
|
||||
case json_type_int:
|
||||
return this->o.c_int;
|
||||
case json_type_double:
|
||||
return this->o.c_double;
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_string:
|
||||
if(sscanf(this->o.c_string, "%d", &cint) == 1) return cint;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_double */
|
||||
|
||||
static int json_object_double_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
{
|
||||
return sprintbuf(pb, "%lf", this->o.c_double);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_double(double d)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_double);
|
||||
if(!this) return NULL;
|
||||
this->_to_json_string = &json_object_double_to_json_string;
|
||||
this->o.c_double = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
double json_object_get_double(struct json_object *this)
|
||||
{
|
||||
double cdouble;
|
||||
|
||||
if(!this) return 0.0;
|
||||
switch(this->o_type) {
|
||||
case json_type_double:
|
||||
return this->o.c_double;
|
||||
case json_type_int:
|
||||
return this->o.c_int;
|
||||
case json_type_boolean:
|
||||
return this->o.c_boolean;
|
||||
case json_type_string:
|
||||
if(sscanf(this->o.c_string, "%lf", &cdouble) == 1) return cdouble;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_string */
|
||||
|
||||
static int json_object_string_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
{
|
||||
sprintbuf(pb, "\"");
|
||||
json_escape_str(pb, this->o.c_string);
|
||||
sprintbuf(pb, "\"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void json_object_string_delete(struct json_object* this)
|
||||
{
|
||||
free(this->o.c_string);
|
||||
json_object_generic_delete(this);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_string(char *s)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_string);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_string_delete;
|
||||
this->_to_json_string = &json_object_string_to_json_string;
|
||||
this->o.c_string = strdup(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_string_len(char *s, int len)
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_string);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_string_delete;
|
||||
this->_to_json_string = &json_object_string_to_json_string;
|
||||
this->o.c_string = strndup(s, len);
|
||||
return this;
|
||||
}
|
||||
|
||||
char* json_object_get_string(struct json_object *this)
|
||||
{
|
||||
if(!this) return NULL;
|
||||
switch(this->o_type) {
|
||||
case json_type_string:
|
||||
return this->o.c_string;
|
||||
default:
|
||||
return json_object_to_json_string(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* json_object_array */
|
||||
|
||||
static int json_object_array_to_json_string(struct json_object* this,
|
||||
struct printbuf *pb)
|
||||
{
|
||||
sprintbuf(pb, "[");
|
||||
for(int i=0; i < json_object_array_length(this); i++) {
|
||||
if(i) sprintbuf(pb, ", ");
|
||||
else sprintbuf(pb, " ");
|
||||
struct json_object *val = json_object_array_get_idx(this, i);
|
||||
if(val == NULL) sprintbuf(pb, "null");
|
||||
else val->_to_json_string(val, pb);
|
||||
}
|
||||
return sprintbuf(pb, " ]");
|
||||
}
|
||||
|
||||
static void json_object_array_entry_free(void *data)
|
||||
{
|
||||
json_object_put((struct json_object*)data);
|
||||
}
|
||||
|
||||
static void json_object_array_delete(struct json_object* this)
|
||||
{
|
||||
array_list_free(this->o.c_array);
|
||||
json_object_generic_delete(this);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_array()
|
||||
{
|
||||
struct json_object *this = json_object_new(json_type_array);
|
||||
if(!this) return NULL;
|
||||
this->_delete = &json_object_array_delete;
|
||||
this->_to_json_string = &json_object_array_to_json_string;
|
||||
this->o.c_array = array_list_new(&json_object_array_entry_free);
|
||||
return this;
|
||||
}
|
||||
|
||||
struct array_list* json_object_get_array(struct json_object *this)
|
||||
{
|
||||
if(!this) return NULL;
|
||||
switch(this->o_type) {
|
||||
case json_type_array:
|
||||
return this->o.c_array;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int json_object_array_length(struct json_object *this)
|
||||
{
|
||||
return array_list_length(this->o.c_array);
|
||||
}
|
||||
|
||||
int json_object_array_add(struct json_object *this,struct json_object *val)
|
||||
{
|
||||
return array_list_add(this->o.c_array, val);
|
||||
}
|
||||
|
||||
int json_object_array_put_idx(struct json_object *this, int idx,
|
||||
struct json_object *val)
|
||||
{
|
||||
return array_list_put_idx(this->o.c_array, idx, val);
|
||||
}
|
||||
|
||||
struct json_object* json_object_array_get_idx(struct json_object *this,
|
||||
int idx)
|
||||
{
|
||||
return (struct json_object*)array_list_get_idx(this->o.c_array, idx);
|
||||
}
|
||||
|
||||
300
json_object.h
Normal file
300
json_object.h
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* $Id: json_object.h,v 1.8 2004/08/07 04:21:27 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _json_object_h_
|
||||
#define _json_object_h_
|
||||
|
||||
#define JSON_OBJECT_DEF_HASH_ENTIRES 16
|
||||
|
||||
#undef FALSE
|
||||
#define FALSE ((boolean)0)
|
||||
|
||||
#undef TRUE
|
||||
#define TRUE ((boolean)1)
|
||||
|
||||
extern char *json_number_chars;
|
||||
extern char *json_hex_chars;
|
||||
|
||||
/* forward structure definitions */
|
||||
|
||||
typedef int boolean;
|
||||
struct printbuf;
|
||||
struct lh_table;
|
||||
struct array_list;
|
||||
struct json_object;
|
||||
|
||||
/* supported object types */
|
||||
|
||||
enum json_type {
|
||||
json_type_null,
|
||||
json_type_boolean,
|
||||
json_type_double,
|
||||
json_type_int,
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string,
|
||||
};
|
||||
|
||||
/* reference counting functions */
|
||||
|
||||
/**
|
||||
* Increment the reference count of json_object
|
||||
* @param this the json_object instance
|
||||
*/
|
||||
extern struct json_object* json_object_get(struct json_object *this);
|
||||
|
||||
/**
|
||||
* Decrement the reference count of json_object and free if it reaches zero
|
||||
* @param this the json_object instance
|
||||
*/
|
||||
extern void json_object_put(struct json_object *this);
|
||||
|
||||
|
||||
/**
|
||||
* Check if the json_object is of a given type
|
||||
* @param this the json_object instance
|
||||
* @param type one of:
|
||||
json_type_boolean,
|
||||
json_type_double,
|
||||
json_type_int,
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string,
|
||||
*/
|
||||
extern int json_object_is_type(struct json_object *this, enum json_type type);
|
||||
|
||||
/**
|
||||
* Get the type of the json_object
|
||||
* @param this the json_object instance
|
||||
* @returns type being one of:
|
||||
json_type_boolean,
|
||||
json_type_double,
|
||||
json_type_int,
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string,
|
||||
*/
|
||||
extern enum json_type json_object_get_type(struct json_object *this);
|
||||
|
||||
|
||||
/** Stringify object to json format
|
||||
* @param this the json_object instance
|
||||
* @returns a string in JSON format
|
||||
*/
|
||||
extern char* json_object_to_json_string(struct json_object *this);
|
||||
|
||||
|
||||
/* object type methods */
|
||||
|
||||
/** Create a new empty object
|
||||
* @returns a json_object of type json_type_object
|
||||
*/
|
||||
extern struct json_object* json_object_new_object();
|
||||
|
||||
/** Get the hashtable of a json_object of type json_type_object
|
||||
* @param this the json_object instance
|
||||
* @returns a linkhash
|
||||
*/
|
||||
extern struct lh_table* json_object_get_object(struct json_object *this);
|
||||
|
||||
/** Add an object field to a json_object of type json_type_object
|
||||
*
|
||||
* The reference count will *not* be incremented. This is to make adding
|
||||
* fields to objects in code more compact. If you want to retain a reference
|
||||
* to an added object you must wrap the passed object with json_object_get
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @param key the object field name (a private copy will be duplicated)
|
||||
* @param val a json_object or NULL member to associate with the given field
|
||||
*/
|
||||
extern void json_object_object_add(struct json_object* this, char *key,
|
||||
struct json_object *val);
|
||||
|
||||
/** Get the json_object associate with a given object field
|
||||
* @param this the json_object instance
|
||||
* @param key the object field name
|
||||
* @returns the json_object associated with the given field name
|
||||
*/
|
||||
extern struct json_object* json_object_object_get(struct json_object* this,
|
||||
char *key);
|
||||
|
||||
/** Delete the given json_object field
|
||||
*
|
||||
* The reference count will be decremented for the deleted object
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @param key the object field name
|
||||
*/
|
||||
extern void json_object_object_del(struct json_object* this, char *key);
|
||||
|
||||
/** Iterate through all keys and values of an object
|
||||
* @param this the json_object instance
|
||||
* @param key the local name for the char* key variable defined in the body
|
||||
* @param val the local name for the json_object* object variable defined in the body
|
||||
*/
|
||||
#define json_object_object_foreach(obj,key,val) \
|
||||
char *key; struct json_object *val; \
|
||||
for(struct lh_entry *entry = json_object_get_object(obj)->head; ({ if(entry) { key = (char*)entry->k; val = (struct json_object*)entry->v; } ; entry; }); entry = entry->next )
|
||||
|
||||
|
||||
/* Array type methods */
|
||||
|
||||
/** Create a new empty json_object of type json_type_array
|
||||
* @returns a json_object of type json_type_array
|
||||
*/
|
||||
extern struct json_object* json_object_new_array();
|
||||
|
||||
/** Get the arraylist of a json_object of type json_type_array
|
||||
* @param this the json_object instance
|
||||
* @returns an arraylist
|
||||
*/
|
||||
extern struct array_list* json_object_get_array(struct json_object *this);
|
||||
|
||||
/** Get the length of a json_object of type json_type_array
|
||||
* @param this the json_object instance
|
||||
* @returns an int
|
||||
*/
|
||||
extern int json_object_array_length(struct json_object *this);
|
||||
|
||||
/** Add an element to the end of a json_object of type json_type_array
|
||||
*
|
||||
* The reference count will *not* be incremented. This is to make adding
|
||||
* fields to objects in code more compact. If you want to retain a reference
|
||||
* to an added object you must wrap the passed object with json_object_get
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @param val the json_object to be added
|
||||
*/
|
||||
extern int json_object_array_add(struct json_object *this,
|
||||
struct json_object *val);
|
||||
|
||||
/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
|
||||
*
|
||||
* The reference count will *not* be incremented. This is to make adding
|
||||
* fields to objects in code more compact. If you want to retain a reference
|
||||
* to an added object you must wrap the passed object with json_object_get
|
||||
*
|
||||
* The reference count of a replaced object will be decremented.
|
||||
*
|
||||
* The array size will be automatically be expanded to the size of the
|
||||
* index if the index is larger than the current size.
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @param idx the index to insert the element at
|
||||
* @param val the json_object to be added
|
||||
*/
|
||||
extern int json_object_array_put_idx(struct json_object *this, int idx,
|
||||
struct json_object *val);
|
||||
|
||||
/** Get the element at specificed index of the array (a json_object of type json_type_array)
|
||||
* @param this the json_object instance
|
||||
* @param idx the index to get the element at
|
||||
* @returns the json_object at the specified index (or NULL)
|
||||
*/
|
||||
extern struct json_object* json_object_array_get_idx(struct json_object *this,
|
||||
int idx);
|
||||
|
||||
/* boolean type methods */
|
||||
|
||||
/** Create a new empty json_object of type json_type_boolean
|
||||
* @param b a boolean TRUE or FALSE (0 or 1)
|
||||
* @returns a json_object of type json_type_boolean
|
||||
*/
|
||||
extern struct json_object* json_object_new_boolean(boolean b);
|
||||
|
||||
/** Get the boolean value of a json_object
|
||||
*
|
||||
* The type is coerced to a boolean if the passed object is not a boolean.
|
||||
* integer and double objects will return FALSE if there value is zero
|
||||
* or TRUE otherwise. If the passed object is a string it will return
|
||||
* TRUE if it has a non zero length. If any other object type is passed
|
||||
* TRUE will be returned if the object is not NULL.
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @returns a boolean
|
||||
*/
|
||||
extern boolean json_object_get_boolean(struct json_object *this);
|
||||
|
||||
|
||||
/* int type methods */
|
||||
|
||||
/** Create a new empty json_object of type json_type_int
|
||||
* @param i the integer
|
||||
* @returns a json_object of type json_type_int
|
||||
*/
|
||||
extern struct json_object* json_object_new_int(int i);
|
||||
|
||||
/** Get the int value of a json_object
|
||||
*
|
||||
* The type is coerced to a int if the passed object is not a int.
|
||||
* double objects will return their integer conversion. Strings will be
|
||||
* parsed as an integer. If no conversion exists then 0 is returned.
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @returns an int
|
||||
*/
|
||||
extern int json_object_get_int(struct json_object *this);
|
||||
|
||||
|
||||
/* double type methods */
|
||||
|
||||
/** Create a new empty json_object of type json_type_double
|
||||
* @param d the double
|
||||
* @returns a json_object of type json_type_double
|
||||
*/
|
||||
extern struct json_object* json_object_new_double(double d);
|
||||
|
||||
/** Get the double value of a json_object
|
||||
*
|
||||
* The type is coerced to a double if the passed object is not a double.
|
||||
* integer objects will return their dboule conversion. Strings will be
|
||||
* parsed as a double. If no conversion exists then 0.0 is returned.
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @returns an double
|
||||
*/
|
||||
extern double json_object_get_double(struct json_object *this);
|
||||
|
||||
|
||||
/* string type methods */
|
||||
|
||||
/** Create a new empty json_object of type json_type_string
|
||||
*
|
||||
* A copy of the string is made and the memory is managed by the json_object
|
||||
*
|
||||
* @param s the string
|
||||
* @returns a json_object of type json_type_string
|
||||
*/
|
||||
extern struct json_object* json_object_new_string(char *s);
|
||||
|
||||
extern struct json_object* json_object_new_string_len(char *s, int len);
|
||||
|
||||
/** Get the string value of a json_object
|
||||
*
|
||||
* If the passed object is not of type json_type_string then the JSON
|
||||
* representation of the object is returned.
|
||||
*
|
||||
* The returned string memory is managed by the json_object and will
|
||||
* be freed when the reference count of the json_object drops to zero.
|
||||
*
|
||||
* @param this the json_object instance
|
||||
* @returns a string
|
||||
*/
|
||||
extern char* json_object_get_string(struct json_object *this);
|
||||
|
||||
#endif
|
||||
25
json_object_private.h
Normal file
25
json_object_private.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef _json_object_private_h_
|
||||
#define _json_object_private_h_
|
||||
|
||||
typedef void (json_object_delete_fn)(struct json_object *o);
|
||||
typedef int (json_object_to_json_string_fn)(struct json_object *o,
|
||||
struct printbuf *pb);
|
||||
|
||||
struct json_object
|
||||
{
|
||||
enum json_type o_type;
|
||||
json_object_delete_fn *_delete;
|
||||
json_object_to_json_string_fn *_to_json_string;
|
||||
int _ref_count;
|
||||
struct printbuf *_pb;
|
||||
union data {
|
||||
boolean c_boolean;
|
||||
double c_double;
|
||||
int c_int;
|
||||
struct lh_table *c_object;
|
||||
struct array_list *c_array;
|
||||
char *c_string;
|
||||
} o;
|
||||
};
|
||||
|
||||
#endif
|
||||
426
json_tokener.c
Normal file
426
json_tokener.c
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* $Id: json_tokener.c,v 1.10 2004/07/27 00:42:31 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "debug.h"
|
||||
#include "printbuf.h"
|
||||
#include "arraylist.h"
|
||||
#include "json_object.h"
|
||||
#include "json_tokener.h"
|
||||
|
||||
|
||||
static struct json_object* json_tokener_do_parse(struct json_tokener *this);
|
||||
|
||||
struct json_object* json_tokener_parse(char * s)
|
||||
{
|
||||
struct json_tokener tok;
|
||||
struct json_object* obj;
|
||||
|
||||
tok.source = s;
|
||||
tok.pos = 0;
|
||||
tok.pb = printbuf_new();
|
||||
obj = json_tokener_do_parse(&tok);
|
||||
printbuf_free(tok.pb);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static struct json_object* json_tokener_do_parse(struct json_tokener *this)
|
||||
{
|
||||
enum json_tokener_state state, saved_state;
|
||||
enum json_tokener_error err = json_tokener_success;
|
||||
struct json_object *current = NULL, *obj;
|
||||
char *obj_field_name = NULL;
|
||||
char quote_char;
|
||||
int deemed_double, start_offset;
|
||||
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_start;
|
||||
|
||||
char c;
|
||||
do {
|
||||
c = this->source[this->pos];
|
||||
switch(state) {
|
||||
|
||||
case json_tokener_state_eatws:
|
||||
if(isspace(c)) {
|
||||
this->pos++;
|
||||
} else if(c == '/') {
|
||||
state = json_tokener_state_comment_start;
|
||||
start_offset = this->pos++;
|
||||
} else {
|
||||
state = saved_state;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_start:
|
||||
switch(c) {
|
||||
case '{':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_object;
|
||||
current = json_object_new_object();
|
||||
this->pos++;
|
||||
break;
|
||||
case '[':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_array;
|
||||
current = json_object_new_array();
|
||||
this->pos++;
|
||||
break;
|
||||
case 'N':
|
||||
case 'n':
|
||||
state = json_tokener_state_null;
|
||||
start_offset = this->pos++;
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
quote_char = c;
|
||||
printbuf_reset(this->pb);
|
||||
state = json_tokener_state_string;
|
||||
start_offset = ++this->pos;
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
case 'F':
|
||||
case 'f':
|
||||
state = json_tokener_state_boolean;
|
||||
start_offset = this->pos++;
|
||||
break;
|
||||
case '0' ... '9':
|
||||
case '-':
|
||||
deemed_double = 0;
|
||||
state = json_tokener_state_number;
|
||||
start_offset = this->pos++;
|
||||
break;
|
||||
default:
|
||||
err = json_tokener_error_parse_unexpected;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_finish:
|
||||
goto out;
|
||||
|
||||
case json_tokener_state_null:
|
||||
if(strncasecmp("null", this->source + start_offset,
|
||||
this->pos - start_offset))
|
||||
return error_ptr(-json_tokener_error_parse_null);
|
||||
if(this->pos - start_offset == 4) {
|
||||
current = NULL;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
this->pos++;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_start:
|
||||
if(c == '*') {
|
||||
state = json_tokener_state_comment;
|
||||
} else if(c == '/') {
|
||||
state = json_tokener_state_comment_eol;
|
||||
} else {
|
||||
err = json_tokener_error_parse_comment;
|
||||
goto out;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment:
|
||||
if(c == '*') state = json_tokener_state_comment_end;
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_eol:
|
||||
if(c == '\n') {
|
||||
if(mc_get_debug()) {
|
||||
char *tmp = strndup(this->source + start_offset,
|
||||
this->pos - start_offset);
|
||||
mc_debug("json_tokener_comment: %s\n", tmp);
|
||||
free(tmp);
|
||||
}
|
||||
state = json_tokener_state_eatws;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_end:
|
||||
if(c == '/') {
|
||||
if(mc_get_debug()) {
|
||||
char *tmp = strndup(this->source + start_offset,
|
||||
this->pos - start_offset + 1);
|
||||
mc_debug("json_tokener_comment: %s\n", tmp);
|
||||
free(tmp);
|
||||
}
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
state = json_tokener_state_comment;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_string:
|
||||
if(c == quote_char) {
|
||||
printbuf_memappend(this->pb, this->source + start_offset,
|
||||
this->pos - start_offset);
|
||||
current = json_object_new_string(this->pb->buf);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == '\\') {
|
||||
saved_state = json_tokener_state_string;
|
||||
state = json_tokener_state_string_escape;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_string_escape:
|
||||
switch(c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
printbuf_memappend(this->pb, this->source + start_offset,
|
||||
this->pos - start_offset - 1);
|
||||
start_offset = this->pos++;
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'b':
|
||||
case 'n':
|
||||
case 'r':
|
||||
case 't':
|
||||
printbuf_memappend(this->pb, this->source + start_offset,
|
||||
this->pos - start_offset - 1);
|
||||
if(c == 'b') printbuf_memappend(this->pb, "\b", 1);
|
||||
else if(c == 'n') printbuf_memappend(this->pb, "\n", 1);
|
||||
else if(c == 'r') printbuf_memappend(this->pb, "\r", 1);
|
||||
else if(c == 't') printbuf_memappend(this->pb, "\t", 1);
|
||||
start_offset = ++this->pos;
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'u':
|
||||
printbuf_memappend(this->pb, this->source + start_offset,
|
||||
this->pos - start_offset - 1);
|
||||
start_offset = ++this->pos;
|
||||
state = json_tokener_state_escape_unicode;
|
||||
break;
|
||||
default:
|
||||
err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_escape_unicode:
|
||||
if(strchr(json_hex_chars, c)) {
|
||||
this->pos++;
|
||||
if(this->pos - start_offset == 4) {
|
||||
unsigned char utf_out[3];
|
||||
unsigned int ucs_char =
|
||||
(hexdigit(*(this->source + start_offset)) << 12) +
|
||||
(hexdigit(*(this->source + start_offset + 1)) << 8) +
|
||||
(hexdigit(*(this->source + start_offset + 2)) << 4) +
|
||||
hexdigit(*(this->source + start_offset + 3));
|
||||
if (ucs_char < 0x80) {
|
||||
utf_out[0] = ucs_char;
|
||||
printbuf_memappend(this->pb, utf_out, 1);
|
||||
} else if (ucs_char < 0x800) {
|
||||
utf_out[0] = 0xc0 | (ucs_char >> 6);
|
||||
utf_out[1] = 0x80 | (ucs_char & 0x3f);
|
||||
printbuf_memappend(this->pb, utf_out, 2);
|
||||
} else {
|
||||
utf_out[0] = 0xe0 | (ucs_char >> 12);
|
||||
utf_out[1] = 0x80 | ((ucs_char >> 6) & 0x3f);
|
||||
utf_out[2] = 0x80 | (ucs_char & 0x3f);
|
||||
printbuf_memappend(this->pb, utf_out, 3);
|
||||
}
|
||||
start_offset = this->pos;
|
||||
state = saved_state;
|
||||
}
|
||||
} else {
|
||||
err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_boolean:
|
||||
if(strncasecmp("true", this->source + start_offset,
|
||||
this->pos - start_offset) == 0) {
|
||||
if(this->pos - start_offset == 4) {
|
||||
current = json_object_new_boolean(1);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
this->pos++;
|
||||
}
|
||||
} else if(strncasecmp("false", this->source + start_offset,
|
||||
this->pos - start_offset) == 0) {
|
||||
if(this->pos - start_offset == 5) {
|
||||
current = json_object_new_boolean(0);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
this->pos++;
|
||||
}
|
||||
} else {
|
||||
err = json_tokener_error_parse_boolean;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_number:
|
||||
if(!c || !strchr(json_number_chars, c)) {
|
||||
int numi;
|
||||
double numd;
|
||||
char *tmp = strndup(this->source + start_offset,
|
||||
this->pos - start_offset);
|
||||
if(!deemed_double && sscanf(tmp, "%d", &numi) == 1) {
|
||||
current = json_object_new_int(numi);
|
||||
} else if(deemed_double && sscanf(tmp, "%lf", &numd) == 1) {
|
||||
current = json_object_new_double(numd);
|
||||
} else {
|
||||
free(tmp);
|
||||
err = json_tokener_error_parse_number;
|
||||
goto out;
|
||||
}
|
||||
free(tmp);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
if(c == '.' || c == 'e') deemed_double = 1;
|
||||
this->pos++;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_array:
|
||||
if(c == ']') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
obj = json_tokener_do_parse(this);
|
||||
if(is_error(obj)) {
|
||||
err = (enum json_tokener_error)obj;
|
||||
goto out;
|
||||
}
|
||||
json_object_array_add(current, obj);
|
||||
saved_state = json_tokener_state_array_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_array_sep:
|
||||
if(c == ']') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == ',') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_array;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
json_object_put(current);
|
||||
return error_ptr(-json_tokener_error_parse_array);
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object:
|
||||
state = json_tokener_state_object_field_start;
|
||||
start_offset = this->pos;
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field_start:
|
||||
if(c == '}') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == '"' || c == '\'') {
|
||||
quote_char = c;
|
||||
printbuf_reset(this->pb);
|
||||
state = json_tokener_state_object_field;
|
||||
start_offset = ++this->pos;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field:
|
||||
if(c == quote_char) {
|
||||
printbuf_memappend(this->pb, this->source + start_offset,
|
||||
this->pos - start_offset);
|
||||
obj_field_name = strdup(this->pb->buf);
|
||||
saved_state = json_tokener_state_object_field_end;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == '\\') {
|
||||
saved_state = json_tokener_state_object_field;
|
||||
state = json_tokener_state_string_escape;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field_end:
|
||||
if(c == ':') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_object_value;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
return error_ptr(-json_tokener_error_parse_object);
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_value:
|
||||
obj = json_tokener_do_parse(this);
|
||||
if(is_error(obj)) {
|
||||
err = (enum json_tokener_error)obj;
|
||||
goto out;
|
||||
}
|
||||
json_object_object_add(current, obj_field_name, obj);
|
||||
free(obj_field_name);
|
||||
obj_field_name = NULL;
|
||||
saved_state = json_tokener_state_object_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_sep:
|
||||
if(c == '}') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == ',') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_object;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
err = json_tokener_error_parse_object;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
} while(c);
|
||||
|
||||
if(state != json_tokener_state_finish &&
|
||||
saved_state != json_tokener_state_finish)
|
||||
err = json_tokener_error_parse_eof;
|
||||
|
||||
out:
|
||||
free(obj_field_name);
|
||||
if(err == json_tokener_success) return current;
|
||||
mc_debug("json_tokener_do_parse: error=%d state=%d char=%c\n",
|
||||
err, state, c);
|
||||
json_object_put(current);
|
||||
return error_ptr(-err);
|
||||
}
|
||||
70
json_tokener.h
Normal file
70
json_tokener.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* $Id: json_tokener.h,v 1.5 2004/07/22 01:20:05 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _json_tokener_h_
|
||||
#define _json_tokener_h_
|
||||
|
||||
#include "json_object.h"
|
||||
|
||||
enum json_tokener_error {
|
||||
json_tokener_success,
|
||||
json_tokener_error_parse_unexpected,
|
||||
json_tokener_error_parse_null,
|
||||
json_tokener_error_parse_boolean,
|
||||
json_tokener_error_parse_number,
|
||||
json_tokener_error_parse_array,
|
||||
json_tokener_error_parse_object,
|
||||
json_tokener_error_parse_string,
|
||||
json_tokener_error_parse_comment,
|
||||
json_tokener_error_parse_eof,
|
||||
};
|
||||
|
||||
enum json_tokener_state {
|
||||
json_tokener_state_eatws,
|
||||
json_tokener_state_start,
|
||||
json_tokener_state_finish,
|
||||
json_tokener_state_null,
|
||||
json_tokener_state_comment_start,
|
||||
json_tokener_state_comment,
|
||||
json_tokener_state_comment_eol,
|
||||
json_tokener_state_comment_end,
|
||||
json_tokener_state_string,
|
||||
json_tokener_state_string_escape,
|
||||
json_tokener_state_escape_unicode,
|
||||
json_tokener_state_boolean,
|
||||
json_tokener_state_number,
|
||||
json_tokener_state_array,
|
||||
json_tokener_state_array_sep,
|
||||
json_tokener_state_object,
|
||||
json_tokener_state_object_field_start,
|
||||
json_tokener_state_object_field,
|
||||
json_tokener_state_object_field_end,
|
||||
json_tokener_state_object_value,
|
||||
json_tokener_state_object_sep,
|
||||
};
|
||||
|
||||
struct json_tokener
|
||||
{
|
||||
char *source;
|
||||
int pos;
|
||||
struct printbuf *pb;
|
||||
};
|
||||
|
||||
extern struct json_object* json_tokener_parse(char *s);
|
||||
|
||||
#endif
|
||||
79
json_util.c
Normal file
79
json_util.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "debug.h"
|
||||
#include "printbuf.h"
|
||||
#include "json_object.h"
|
||||
#include "json_tokener.h"
|
||||
#include "json_util.h"
|
||||
|
||||
|
||||
struct json_object* json_object_from_file(char *filename)
|
||||
{
|
||||
struct printbuf *pb;
|
||||
struct json_object *obj;
|
||||
char buf[JSON_FILE_BUF_SIZE];
|
||||
int fd, ret;
|
||||
|
||||
if((fd = open(filename, O_RDONLY)) < 0) {
|
||||
mc_error("json_object_from_file: error reading file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return error_ptr(-1);
|
||||
}
|
||||
if(!(pb = printbuf_new())) {
|
||||
mc_error("json_object_from_file: printbuf_new failed\n");
|
||||
return error_ptr(-1);
|
||||
}
|
||||
while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
|
||||
printbuf_memappend(pb, buf, ret);
|
||||
}
|
||||
close(fd);
|
||||
if(ret < 0) {
|
||||
mc_abort("json_object_from_file: error reading file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
printbuf_free(pb);
|
||||
return error_ptr(-1);
|
||||
}
|
||||
obj = json_tokener_parse(pb->buf);
|
||||
printbuf_free(pb);
|
||||
return obj;
|
||||
}
|
||||
|
||||
int json_object_to_file(char *filename, struct json_object *obj)
|
||||
{
|
||||
char *json_str;
|
||||
int fd, ret, wpos, wsize;
|
||||
|
||||
if(!obj) {
|
||||
mc_error("json_object_to_file: object is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
|
||||
mc_error("json_object_to_file: error opening file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if(!(json_str = json_object_to_json_string(obj))) return -1;
|
||||
wsize = strlen(json_str);
|
||||
wpos = 0;
|
||||
while(wpos < wsize) {
|
||||
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
|
||||
close(fd);
|
||||
mc_error("json_object_to_file: error writing file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
wpos += ret;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
13
json_util.h
Normal file
13
json_util.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _json_util_h_
|
||||
#define _json_util_h_
|
||||
|
||||
#include "json_object.h"
|
||||
|
||||
|
||||
#define JSON_FILE_BUF_SIZE 4096
|
||||
|
||||
/* utlitiy functions */
|
||||
extern struct json_object* json_object_from_file(char *filename);
|
||||
extern int json_object_to_file(char *filename, struct json_object *obj);
|
||||
|
||||
#endif
|
||||
225
linkhash.c
Normal file
225
linkhash.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* $Id: linkhash.c,v 1.2 2004/07/21 01:24:33 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "linkhash.h"
|
||||
|
||||
|
||||
void lh_abort(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
vprintf(msg, ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
unsigned long lh_ptr_hash(void *k)
|
||||
{
|
||||
return ((long)k * LH_PRIME) >> 4;
|
||||
}
|
||||
|
||||
|
||||
int lh_ptr_equal(void *k1, void *k2)
|
||||
{
|
||||
return (k1 == k2);
|
||||
}
|
||||
|
||||
|
||||
unsigned long lh_char_hash(void *k)
|
||||
{
|
||||
unsigned int h = 0;
|
||||
const char* data = k;
|
||||
|
||||
while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
int lh_char_equal(void *k1, void *k2)
|
||||
{
|
||||
return (strcmp((char*)k1, (char*)k2) == 0);
|
||||
}
|
||||
|
||||
|
||||
struct lh_table* lh_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn,
|
||||
lh_hash_fn *hash_fn,
|
||||
lh_equal_fn *equal_fn)
|
||||
{
|
||||
int i;
|
||||
struct lh_table *t;
|
||||
|
||||
t = calloc(1, sizeof(struct lh_table));
|
||||
if(!t) lh_abort("lh_table_new: calloc failed\n");
|
||||
t->count = 0;
|
||||
t->size = size;
|
||||
t->name = name;
|
||||
t->table = calloc(size, sizeof(struct lh_entry));
|
||||
if(!t->table) lh_abort("lh_table_new: calloc failed\n");
|
||||
t->free_fn = free_fn;
|
||||
t->hash_fn = hash_fn;
|
||||
t->equal_fn = equal_fn;
|
||||
for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
struct lh_table* lh_kchar_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn)
|
||||
{
|
||||
return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
|
||||
}
|
||||
|
||||
|
||||
struct lh_table* lh_kptr_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn)
|
||||
{
|
||||
return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
|
||||
}
|
||||
|
||||
|
||||
void lh_table_resize(struct lh_table *t, int new_size)
|
||||
{
|
||||
struct lh_table *new_t;
|
||||
struct lh_entry *ent;
|
||||
|
||||
new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
|
||||
ent = t->head;
|
||||
while(ent) {
|
||||
lh_table_insert(new_t, ent->k, ent->v);
|
||||
ent = ent->next;
|
||||
}
|
||||
free(t->table);
|
||||
t->table = new_t->table;
|
||||
t->size = new_size;
|
||||
t->head = new_t->head;
|
||||
t->tail = new_t->tail;
|
||||
t->resizes++;
|
||||
free(new_t);
|
||||
}
|
||||
|
||||
|
||||
void lh_table_free(struct lh_table *t)
|
||||
{
|
||||
struct lh_entry *c;
|
||||
for(c = t->head; c != NULL; c = c->next) {
|
||||
if(t->free_fn) {
|
||||
t->free_fn(c);
|
||||
}
|
||||
}
|
||||
free(t->table);
|
||||
free(t);
|
||||
}
|
||||
|
||||
|
||||
int lh_table_insert(struct lh_table *t, void *k, void *v)
|
||||
{
|
||||
unsigned long h, n;
|
||||
|
||||
t->inserts++;
|
||||
if(t->count > t->size * 0.66) lh_table_resize(t, t->size * 2);
|
||||
|
||||
h = t->hash_fn(k);
|
||||
n = h % t->size;
|
||||
|
||||
while( 1 ) {
|
||||
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
|
||||
t->collisions++;
|
||||
if(++n == t->size) n = 0;
|
||||
}
|
||||
|
||||
t->table[n].k = k;
|
||||
t->table[n].v = v;
|
||||
t->count++;
|
||||
|
||||
if(t->head == NULL) {
|
||||
t->head = t->tail = &t->table[n];
|
||||
t->table[n].next = t->table[n].prev = NULL;
|
||||
} else {
|
||||
t->tail->next = &t->table[n];
|
||||
t->table[n].prev = t->tail;
|
||||
t->table[n].next = NULL;
|
||||
t->tail = &t->table[n];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k)
|
||||
{
|
||||
unsigned long h = t->hash_fn(k);
|
||||
unsigned long n = h % t->size;
|
||||
|
||||
t->lookups++;
|
||||
while( 1 ) {
|
||||
if(t->table[n].k == LH_EMPTY) return NULL;
|
||||
if(t->table[n].k != LH_FREED &&
|
||||
t->equal_fn(t->table[n].k, k)) return &t->table[n];
|
||||
if(++n == t->size) n = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* lh_table_lookup(struct lh_table *t, void *k)
|
||||
{
|
||||
struct lh_entry *e = lh_table_lookup_entry(t, k);
|
||||
if(e) return e->v;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
|
||||
{
|
||||
int n = e - t->table;
|
||||
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
|
||||
t->count--;
|
||||
if(t->free_fn) t->free_fn(e);
|
||||
t->table[n].v = NULL;
|
||||
t->table[n].k = LH_FREED;
|
||||
if(t->tail == &t->table[n] && t->head == &t->table[n]) {
|
||||
t->head = t->tail = NULL;
|
||||
} else if (t->head == &t->table[n]) {
|
||||
t->head->next->prev = NULL;
|
||||
t->head = t->head->next;
|
||||
} else if (t->tail == &t->table[n]) {
|
||||
t->tail->prev->next = NULL;
|
||||
t->tail = t->tail->prev;
|
||||
} else {
|
||||
t->table[n].prev->next = t->table[n].next;
|
||||
t->table[n].next->prev = t->table[n].prev;
|
||||
}
|
||||
t->table[n].next = t->table[n].prev = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int lh_table_delete(struct lh_table *t, void *k)
|
||||
{
|
||||
struct lh_entry *e = lh_table_lookup_entry(t, k);
|
||||
if(!e) return -1;
|
||||
return lh_table_delete_entry(t, e);
|
||||
}
|
||||
|
||||
270
linkhash.h
Normal file
270
linkhash.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* $Id: linkhash.h,v 1.3 2004/08/07 03:29:47 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _linkhash_h_
|
||||
#define _linkhash_h_
|
||||
|
||||
/**
|
||||
* golden prime used in hash functions
|
||||
*/
|
||||
#define LH_PRIME 0x9e370001UL
|
||||
|
||||
/**
|
||||
* sentinel pointer value for empty slots
|
||||
*/
|
||||
#define LH_EMPTY (void*)-1
|
||||
|
||||
/**
|
||||
* sentinel pointer value for freed slots
|
||||
*/
|
||||
#define LH_FREED (void*)-2
|
||||
|
||||
|
||||
struct lh_entry;
|
||||
|
||||
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef void (lh_entry_free_fn) (struct lh_entry *e);
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef unsigned long (lh_hash_fn) (void *k);
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef int (lh_equal_fn) (void *k1, void *k2);
|
||||
|
||||
/**
|
||||
* An entry in the hash table
|
||||
*/
|
||||
struct lh_entry {
|
||||
/**
|
||||
* The key.
|
||||
*/
|
||||
void *k;
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
void *v;
|
||||
/**
|
||||
* The next entry
|
||||
*/
|
||||
struct lh_entry *next;
|
||||
/**
|
||||
* The previous entry.
|
||||
*/
|
||||
struct lh_entry *prev;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The hash table structure.
|
||||
*/
|
||||
struct lh_table {
|
||||
/**
|
||||
* Size of our hash.
|
||||
*/
|
||||
int size;
|
||||
/**
|
||||
* Numbers of entries.
|
||||
*/
|
||||
int count;
|
||||
|
||||
/**
|
||||
* Number of collisions.
|
||||
*/
|
||||
int collisions;
|
||||
|
||||
/**
|
||||
* Number of resizes.
|
||||
*/
|
||||
int resizes;
|
||||
|
||||
/**
|
||||
* Number of lookups.
|
||||
*/
|
||||
int lookups;
|
||||
|
||||
/**
|
||||
* Number of inserts.
|
||||
*/
|
||||
int inserts;
|
||||
|
||||
/**
|
||||
* Number of deletes.
|
||||
*/
|
||||
int deletes;
|
||||
|
||||
/**
|
||||
* Name of the hash table.
|
||||
*/
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* The first entry.
|
||||
*/
|
||||
struct lh_entry *head;
|
||||
|
||||
/**
|
||||
* The last entry.
|
||||
*/
|
||||
struct lh_entry *tail;
|
||||
|
||||
struct lh_entry *table;
|
||||
|
||||
/**
|
||||
* A pointer onto the function responsible for freeing an entry.
|
||||
*/
|
||||
lh_entry_free_fn *free_fn;
|
||||
lh_hash_fn *hash_fn;
|
||||
lh_equal_fn *equal_fn;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pre-defined hash and equality functions
|
||||
*/
|
||||
extern unsigned long lh_ptr_hash(void *k);
|
||||
extern int lh_ptr_equal(void *k1, void *k2);
|
||||
|
||||
extern unsigned long lh_char_hash(void *k);
|
||||
extern int lh_char_equal(void *k1, void *k2);
|
||||
|
||||
|
||||
/**
|
||||
* Convenience list iterator.
|
||||
*/
|
||||
#define lh_foreach(table, entry) \
|
||||
for(entry = table->head; entry; entry = entry->next)
|
||||
|
||||
/**
|
||||
* lh_foreach_safe allows calling of deletion routine while iterating.
|
||||
*/
|
||||
#define lh_foreach_safe(table, entry, tmp) \
|
||||
for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new linkhash table.
|
||||
* @param size initial table size. The table is automatically resized
|
||||
* although this incurs a performance penalty.
|
||||
* @param name the table name.
|
||||
* @param free_fn callback function used to free memory for entries
|
||||
* when lh_table_free or lh_table_delete is called.
|
||||
* If NULL is provided, then memory for keys and values
|
||||
* must be freed by the caller.
|
||||
* @param hash_fn function used to hash keys. 2 standard ones are defined:
|
||||
* lh_ptr_hash and lh_char_hash for hashing pointer values
|
||||
* and C strings respectively.
|
||||
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
|
||||
* lh_ptr_hash and lh_char_hash for comparing pointer values
|
||||
* and C strings respectively.
|
||||
* @return a pointer onto the linkhash table.
|
||||
*/
|
||||
extern struct lh_table* lh_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn,
|
||||
lh_hash_fn *hash_fn,
|
||||
lh_equal_fn *equal_fn);
|
||||
|
||||
/**
|
||||
* Convenience function to create a new linkhash
|
||||
* table with char keys.
|
||||
* @param size initial table size.
|
||||
* @param name table name.
|
||||
* @param free_fn callback function used to free memory for entries.
|
||||
* @return a pointer onto the linkhash table.
|
||||
*/
|
||||
extern struct lh_table* lh_kchar_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn);
|
||||
|
||||
|
||||
/**
|
||||
* Convenience function to create a new linkhash
|
||||
* table with ptr keys.
|
||||
* @param size initial table size.
|
||||
* @param name table name.
|
||||
* @param free_fn callback function used to free memory for entries.
|
||||
* @return a pointer onto the linkhash table.
|
||||
*/
|
||||
extern struct lh_table* lh_kptr_table_new(int size, char *name,
|
||||
lh_entry_free_fn *free_fn);
|
||||
|
||||
|
||||
/**
|
||||
* Free a linkhash table.
|
||||
* If a callback free function is provided then it is called for all
|
||||
* entries in the table.
|
||||
* @param t table to free.
|
||||
*/
|
||||
extern void lh_table_free(struct lh_table *t);
|
||||
|
||||
|
||||
/**
|
||||
* Insert a record into the table.
|
||||
* @param t the table to insert into.
|
||||
* @param k a pointer to the key to insert.
|
||||
* @param v a pointer to the value to insert.
|
||||
*/
|
||||
extern int lh_table_insert(struct lh_table *t, void *k, void *v);
|
||||
|
||||
|
||||
/**
|
||||
* Lookup a record into the table.
|
||||
* @param t the table to lookup
|
||||
* @param k a pointer to the key to lookup
|
||||
* @return a pointer to the record structure of the value or NULL if it does not exist.
|
||||
*/
|
||||
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k);
|
||||
|
||||
/**
|
||||
* Lookup a record into the table
|
||||
* @param t the table to lookup
|
||||
* @param k a pointer to the key to lookup
|
||||
* @return a pointer to the found value or NULL if it does not exist.
|
||||
*/
|
||||
extern void* lh_table_lookup(struct lh_table *t, void *k);
|
||||
|
||||
|
||||
/**
|
||||
* Delete a record from the table.
|
||||
* If a callback free function is provided then it is called for the
|
||||
* for the item being deleted.
|
||||
* @param t the table to delete from.
|
||||
* @param e a pointer to the entry to delete.
|
||||
* @return 0 if the item was deleted.
|
||||
* @return -1 if it was not found.
|
||||
*/
|
||||
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
|
||||
|
||||
|
||||
/**
|
||||
* Delete a record from the table.
|
||||
* If a callback free function is provided then it is called for the
|
||||
* for the item being deleted.
|
||||
* @param t the table to delete from.
|
||||
* @param k a pointer to the key to delete.
|
||||
* @return 0 if the item was deleted.
|
||||
* @return -1 if it was not found.
|
||||
*/
|
||||
extern int lh_table_delete(struct lh_table *t, void *k);
|
||||
|
||||
|
||||
#endif
|
||||
106
printbuf.c
Normal file
106
printbuf.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* $Id: printbuf.c,v 1.3 2004/08/07 03:12:21 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "debug.h"
|
||||
#include "printbuf.h"
|
||||
|
||||
|
||||
struct printbuf* printbuf_new()
|
||||
{
|
||||
struct printbuf *p;
|
||||
|
||||
if(!(p = calloc(1, sizeof(struct printbuf)))) return NULL;
|
||||
p->size = 32;
|
||||
p->bpos = 0;
|
||||
if(!(p->buf = malloc(p->size))) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
int printbuf_memappend(struct printbuf *p, char *buf, int size)
|
||||
{
|
||||
char *t;
|
||||
if(p->size - p->bpos <= size) {
|
||||
int new_size = max(p->size * 2, p->bpos + size + 8);
|
||||
#if 0
|
||||
mc_debug("printbuf_memappend: realloc "
|
||||
"bpos=%d wrsize=%d old_size=%d new_size=%d\n",
|
||||
p->bpos, size, p->size, new_size);
|
||||
#endif
|
||||
if(!(t = realloc(p->buf, new_size))) return -1;
|
||||
p->size = new_size;
|
||||
p->buf = t;
|
||||
}
|
||||
memcpy(p->buf + p->bpos, buf, size);
|
||||
p->bpos += size;
|
||||
p->buf[p->bpos]= '\0';
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
int sprintbuf(struct printbuf *p, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *t;
|
||||
int size;
|
||||
char buf[128];
|
||||
|
||||
/* user stack buffer first */
|
||||
va_start(ap, msg);
|
||||
size = vsnprintf(buf, 128, msg, ap);
|
||||
va_end(ap);
|
||||
/* if string is greater than stack buffer, then use dynamic string
|
||||
with vasprintf. Note: some implementation of vsnprintf return -1
|
||||
if output is truncated whereas some return the number of bytes that
|
||||
would have been writeen - this code handles both cases. */
|
||||
if(size == -1 || size > 127) {
|
||||
int ret;
|
||||
va_start(ap, msg);
|
||||
if((size = vasprintf(&t, msg, ap)) == -1) return -1;
|
||||
va_end(ap);
|
||||
ret = printbuf_memappend(p, t, size);
|
||||
free(t);
|
||||
return ret;
|
||||
} else {
|
||||
return printbuf_memappend(p, buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printbuf_reset(struct printbuf *p)
|
||||
{
|
||||
p->buf[0] = '\0';
|
||||
p->bpos = 0;
|
||||
}
|
||||
|
||||
void printbuf_free(struct printbuf *p)
|
||||
{
|
||||
if(p) {
|
||||
free(p->buf);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
43
printbuf.h
Normal file
43
printbuf.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* $Id: printbuf.h,v 1.2 2004/07/21 01:24:33 mclark Exp $
|
||||
*
|
||||
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public (LGPL)
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details: http://www.gnu.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _printbuf_h_
|
||||
#define _printbuf_h_
|
||||
|
||||
struct printbuf {
|
||||
char *buf;
|
||||
int bpos;
|
||||
int size;
|
||||
};
|
||||
|
||||
extern struct printbuf*
|
||||
printbuf_new();
|
||||
|
||||
extern int
|
||||
printbuf_memappend(struct printbuf *p, char *buf, int size);
|
||||
|
||||
extern int
|
||||
sprintbuf(struct printbuf *p, const char *msg, ...);
|
||||
|
||||
extern void
|
||||
printbuf_reset(struct printbuf *p);
|
||||
|
||||
extern void
|
||||
printbuf_free(struct printbuf *p);
|
||||
|
||||
#endif
|
||||
134
test1.c
Normal file
134
test1.c
Normal file
@@ -0,0 +1,134 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "json.h"
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct json_object *my_string, *my_int, *my_object, *my_array;
|
||||
struct json_object *new_obj;
|
||||
|
||||
my_string = json_object_new_string("\t");
|
||||
printf("my_string=%s\n", json_object_get_string(my_string));
|
||||
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
|
||||
json_object_put(my_string);
|
||||
|
||||
my_string = json_object_new_string("foo");
|
||||
printf("my_string=%s\n", json_object_get_string(my_string));
|
||||
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
|
||||
|
||||
my_int = json_object_new_int(9);
|
||||
printf("my_int=%d\n", json_object_get_int(my_int));
|
||||
printf("my_int.to_string()=%s\n", json_object_to_json_string(my_int));
|
||||
|
||||
my_array = json_object_new_array();
|
||||
json_object_array_add(my_array, json_object_new_int(1));
|
||||
json_object_array_add(my_array, json_object_new_int(2));
|
||||
json_object_array_add(my_array, json_object_new_int(3));
|
||||
json_object_array_put_idx(my_array, 4, json_object_new_int(5));
|
||||
printf("my_array=\n");
|
||||
for(int i=0; i < json_object_array_length(my_array); i++) {
|
||||
struct json_object *obj = json_object_array_get_idx(my_array, i);
|
||||
printf("\t[%d]=%s\n", i, json_object_to_json_string(obj));
|
||||
}
|
||||
printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
|
||||
|
||||
my_object = json_object_new_object();
|
||||
json_object_object_add(my_object, "abc", json_object_new_int(12));
|
||||
json_object_object_add(my_object, "foo", json_object_new_string("bar"));
|
||||
json_object_object_add(my_object, "bool0", json_object_new_boolean(0));
|
||||
json_object_object_add(my_object, "bool1", json_object_new_boolean(1));
|
||||
json_object_object_add(my_object, "baz", json_object_new_string("bang"));
|
||||
json_object_object_add(my_object, "baz", json_object_new_string("fark"));
|
||||
json_object_object_del(my_object, "baz");
|
||||
json_object_object_add(my_object, "arr", my_array);
|
||||
printf("my_object=\n");
|
||||
json_object_object_foreach(my_object, key, val) {
|
||||
printf("\t%s: %s\n", key, json_object_to_json_string(val));
|
||||
}
|
||||
printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object));
|
||||
|
||||
new_obj = json_tokener_parse("\"\003\"");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("/* hello */\"foo\"");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("// hello\n\"foo\"");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\"");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("null");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("True");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("12");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("12.3");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("[\"\\n\"]");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("[\"\\nabc\\n\"]");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("[null]");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("[]");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("{}");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("{ \"foo\": \"bar\" }");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
new_obj = json_tokener_parse("foo");
|
||||
if(is_error(new_obj)) printf("got error as expected\n");
|
||||
|
||||
json_object_put(my_string);
|
||||
json_object_put(my_int);
|
||||
json_object_put(my_object);
|
||||
//json_object_put(my_array);
|
||||
|
||||
return 0;
|
||||
}
|
||||
19
test2.c
Normal file
19
test2.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "json.h"
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct json_object *new_obj;
|
||||
|
||||
mc_set_debug(1);
|
||||
|
||||
new_obj = json_tokener_parse("/* more difficult test case */ { \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }");
|
||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
||||
json_object_put(new_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user