* Add int64 support. Two new functions json_object_net_int64 and
json_object_get_int64. Binary compatibility preserved.
Eric Haszlakiewicz, EHASZLA at transunion com
Rui Miguel Silva Seabra, rms at 1407 dot org
git-svn-id: http://svn.metaparadigm.com/svn/json-c/trunk@56 327403b1-1117-474d-bef2-5cb71233fd97
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
0.10
|
||||
* Add int64 support. Two new functions json_object_net_int64 and
|
||||
json_object_get_int64. Binary compatibility preserved.
|
||||
Eric Haszlakiewicz, EHASZLA at transunion com
|
||||
Rui Miguel Silva Seabra, rms at 1407 dot org
|
||||
* Fix subtle bug in linkhash where lookup could hang after all slots
|
||||
were filled then successively freed.
|
||||
Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com
|
||||
|
||||
2
Doxyfile
2
Doxyfile
@@ -23,7 +23,7 @@ PROJECT_NAME = json-c
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.2
|
||||
PROJECT_NUMBER = 0.10
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
||||
30
Makefile.am
30
Makefile.am
@@ -9,16 +9,17 @@ pkgconfig_DATA = json.pc
|
||||
|
||||
libjsonincludedir = $(includedir)/json
|
||||
libjsoninclude_HEADERS = \
|
||||
json.h \
|
||||
arraylist.h \
|
||||
bits.h \
|
||||
debug.h \
|
||||
linkhash.h \
|
||||
arraylist.h \
|
||||
printbuf.h \
|
||||
json_util.h \
|
||||
json.h \
|
||||
json_inttypes.h \
|
||||
json_object.h \
|
||||
json_object_private.h \
|
||||
json_tokener.h
|
||||
json_tokener.h \
|
||||
json_util.h \
|
||||
linkhash.h \
|
||||
printbuf.h
|
||||
|
||||
libjson_la_LDFLAGS = -version-info 0:1:0
|
||||
|
||||
@@ -31,7 +32,7 @@ libjson_la_SOURCES = \
|
||||
linkhash.c \
|
||||
printbuf.c
|
||||
|
||||
check_PROGRAMS = test1 test2 test3 test4
|
||||
check_PROGRAMS = test1 test2 test4 test_parse_int64
|
||||
|
||||
test1_SOURCES = test1.c
|
||||
test1_LDADD = $(lib_LTLIBRARIES)
|
||||
@@ -39,8 +40,17 @@ test1_LDADD = $(lib_LTLIBRARIES)
|
||||
test2_SOURCES = test2.c
|
||||
test2_LDADD = $(lib_LTLIBRARIES)
|
||||
|
||||
test3_SOURCES = test3.c
|
||||
test3_LDADD = $(lib_LTLIBRARIES)
|
||||
|
||||
test4_SOURCES = test4.c
|
||||
test4_LDADD = $(lib_LTLIBRARIES)
|
||||
|
||||
test_parse_int64_SOURCES = test_parse_int64.c
|
||||
test_parse_int64_LDADD = $(lib_LTLIBRARIES)
|
||||
|
||||
TESTS = test1.test test2.test test4.test parse_int64.test
|
||||
EXTRA_DIST += $(TESTS)
|
||||
testsubdir=testSubDir
|
||||
TESTS_ENVIRONMENT = top_builddir=$(top_builddir)
|
||||
|
||||
distclean-local:
|
||||
-rm -rf $(testsubdir)
|
||||
|
||||
|
||||
@@ -80,10 +80,6 @@
|
||||
/* Define to 1 if you have the `vsyslog' function. */
|
||||
#undef HAVE_VSYSLOG
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
@@ -117,5 +113,5 @@
|
||||
/* Define to rpl_realloc if the replacement function should be used. */
|
||||
#undef realloc
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
21
json_inttypes.h
Normal file
21
json_inttypes.h
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
#ifndef _json_inttypes_h_
|
||||
#define _json_inttypes_h_
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
|
||||
/* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */
|
||||
typedef __int64 int64_t;
|
||||
#define PRId64 "I64d"
|
||||
#define SCNd64 "I64d"
|
||||
|
||||
#else
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
/* inttypes.h includes stdint.h */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -20,8 +20,10 @@
|
||||
#include "printbuf.h"
|
||||
#include "linkhash.h"
|
||||
#include "arraylist.h"
|
||||
#include "json_inttypes.h"
|
||||
#include "json_object.h"
|
||||
#include "json_object_private.h"
|
||||
#include "json_util.h"
|
||||
|
||||
#if !HAVE_STRNDUP
|
||||
char* strndup(const char* str, size_t n);
|
||||
@@ -41,6 +43,7 @@ static const char* json_type_name[] = {
|
||||
"object",
|
||||
"array",
|
||||
"string",
|
||||
"int64",
|
||||
};
|
||||
#endif /* REFCOUNT_DEBUG */
|
||||
|
||||
@@ -304,6 +307,8 @@ boolean json_object_get_boolean(struct json_object *jso)
|
||||
return jso->o.c_boolean;
|
||||
case json_type_int:
|
||||
return (jso->o.c_int != 0);
|
||||
case json_type_int64:
|
||||
return (jso->o.c_int64 != 0);
|
||||
case json_type_double:
|
||||
return (jso->o.c_double != 0);
|
||||
case json_type_string:
|
||||
@@ -322,7 +327,11 @@ static int json_object_int_to_json_string(struct json_object* jso,
|
||||
return sprintbuf(pb, "%d", jso->o.c_int);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_int(int i)
|
||||
static int json_object_int64_to_json_string(struct json_object* jso, struct printbuf *pb) {
|
||||
return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_int(int32_t i)
|
||||
{
|
||||
struct json_object *jso = json_object_new(json_type_int);
|
||||
if(!jso) return NULL;
|
||||
@@ -331,20 +340,69 @@ struct json_object* json_object_new_int(int i)
|
||||
return jso;
|
||||
}
|
||||
|
||||
int json_object_get_int(struct json_object *jso)
|
||||
int32_t json_object_get_int(struct json_object *jso)
|
||||
{
|
||||
int cint;
|
||||
if(!jso) return 0;
|
||||
|
||||
enum json_type o_type = jso->o_type;
|
||||
int64_t cint64 = jso->o.c_int64;
|
||||
|
||||
if (o_type == json_type_string)
|
||||
{
|
||||
/*
|
||||
* Parse strings into 64-bit numbers, then use the
|
||||
* 64-to-32-bit number handling below.
|
||||
*/
|
||||
if (json_parse_int64(jso->o.c_string, &cint64) != 0)
|
||||
return 0; /* whoops, it didn't work. */
|
||||
o_type = json_type_int64;
|
||||
}
|
||||
|
||||
switch(jso->o_type) {
|
||||
case json_type_int:
|
||||
return jso->o.c_int;
|
||||
case json_type_int64:
|
||||
/* Make sure we return the correct values for out of range numbers. */
|
||||
if (cint64 <= INT32_MIN)
|
||||
return INT32_MIN;
|
||||
else if (cint64 >= INT32_MAX)
|
||||
return INT32_MAX;
|
||||
else
|
||||
return (int32_t)cint64;
|
||||
case json_type_double:
|
||||
return (int32_t)jso->o.c_double;
|
||||
case json_type_boolean:
|
||||
return jso->o.c_boolean;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct json_object* json_object_new_int64(int64_t i)
|
||||
{
|
||||
struct json_object *jso = json_object_new(json_type_int64);
|
||||
if(!jso) return NULL;
|
||||
jso->_to_json_string = &json_object_int64_to_json_string;
|
||||
jso->o.c_int64 = i;
|
||||
return jso;
|
||||
}
|
||||
|
||||
int64_t json_object_get_int64(struct json_object *jso)
|
||||
{
|
||||
int64_t cint;
|
||||
|
||||
if(!jso) return 0;
|
||||
switch(jso->o_type) {
|
||||
case json_type_int:
|
||||
return jso->o.c_int;
|
||||
return (int64_t)jso->o.c_int;
|
||||
case json_type_int64:
|
||||
return jso->o.c_int64;
|
||||
case json_type_double:
|
||||
return (int)jso->o.c_double;
|
||||
return (int64_t)jso->o.c_double;
|
||||
case json_type_boolean:
|
||||
return jso->o.c_boolean;
|
||||
case json_type_string:
|
||||
if(sscanf(jso->o.c_string, "%d", &cint) == 1) return cint;
|
||||
if (json_parse_int64(jso->o.c_string, &cint) == 0) return cint;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -378,6 +436,8 @@ double json_object_get_double(struct json_object *jso)
|
||||
return jso->o.c_double;
|
||||
case json_type_int:
|
||||
return jso->o.c_int;
|
||||
case json_type_int64:
|
||||
return jso->o.c_int64;
|
||||
case json_type_boolean:
|
||||
return jso->o.c_boolean;
|
||||
case json_type_string:
|
||||
|
||||
@@ -46,7 +46,8 @@ typedef enum json_type {
|
||||
json_type_int,
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string
|
||||
json_type_string,
|
||||
json_type_int64
|
||||
} json_type;
|
||||
|
||||
/* reference counting functions */
|
||||
@@ -74,6 +75,7 @@ extern void json_object_put(struct json_object *obj);
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string,
|
||||
json_type_int64,
|
||||
*/
|
||||
extern int json_object_is_type(struct json_object *obj, enum json_type type);
|
||||
|
||||
@@ -87,6 +89,7 @@ extern int json_object_is_type(struct json_object *obj, enum json_type type);
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string,
|
||||
json_type_int64,
|
||||
*/
|
||||
extern enum json_type json_object_get_type(struct json_object *obj);
|
||||
|
||||
@@ -252,7 +255,15 @@ extern boolean json_object_get_boolean(struct json_object *obj);
|
||||
* @param i the integer
|
||||
* @returns a json_object of type json_type_int
|
||||
*/
|
||||
extern struct json_object* json_object_new_int(int i);
|
||||
extern struct json_object* json_object_new_int(int32_t i);
|
||||
|
||||
|
||||
/** Create a new empty json_object of type json_type_int64
|
||||
* @param i the integer
|
||||
* @returns a json_object of type json_type_int64
|
||||
*/
|
||||
extern struct json_object* json_object_new_int64(int64_t i);
|
||||
|
||||
|
||||
/** Get the int value of a json_object
|
||||
*
|
||||
@@ -263,7 +274,18 @@ extern struct json_object* json_object_new_int(int i);
|
||||
* @param obj the json_object instance
|
||||
* @returns an int
|
||||
*/
|
||||
extern int json_object_get_int(struct json_object *obj);
|
||||
extern int32_t json_object_get_int(struct json_object *obj);
|
||||
|
||||
/** Get the int value of a json_object
|
||||
*
|
||||
* The type is coerced to a int64 if the passed object is not a int64.
|
||||
* double objects will return their int64 conversion. Strings will be
|
||||
* parsed as an int64. If no conversion exists then 0 is returned.
|
||||
*
|
||||
* @param obj the json_object instance
|
||||
* @returns an int64
|
||||
*/
|
||||
extern int64_t json_object_get_int64(struct json_object *obj);
|
||||
|
||||
|
||||
/* double type methods */
|
||||
|
||||
@@ -30,7 +30,8 @@ struct json_object
|
||||
union data {
|
||||
boolean c_boolean;
|
||||
double c_double;
|
||||
int c_int;
|
||||
int32_t c_int;
|
||||
int64_t c_int64;
|
||||
struct lh_table *c_object;
|
||||
struct array_list *c_array;
|
||||
char *c_string;
|
||||
|
||||
@@ -20,14 +20,16 @@
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "debug.h"
|
||||
#include "printbuf.h"
|
||||
#include "arraylist.h"
|
||||
#include "json_inttypes.h"
|
||||
#include "json_object.h"
|
||||
#include "json_tokener.h"
|
||||
|
||||
#include "json_util.h"
|
||||
|
||||
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
|
||||
/* MSC has the version as _strnicmp */
|
||||
@@ -542,10 +544,20 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
||||
printbuf_memappend_fast(tok->pb, case_start, case_len);
|
||||
}
|
||||
{
|
||||
int numi;
|
||||
int64_t num64;
|
||||
double numd;
|
||||
if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
|
||||
current = json_object_new_int(numi);
|
||||
if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
|
||||
// Decode the type based on the value range to keep compatibilty
|
||||
// with code that checks the type of objects. i.e. this:
|
||||
// json_object_get_type(o) == json_type_int
|
||||
// will continue to work.
|
||||
// The other option would be to eliminate any distinction between
|
||||
// int and int64 types, but that would change the ABI of
|
||||
// json_object_get_int().
|
||||
if (num64 < INT32_MAX && num64 > INT32_MIN)
|
||||
current = json_object_new_int(num64);
|
||||
else
|
||||
current = json_object_new_int64(num64);
|
||||
} else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
|
||||
current = json_object_new_double(numd);
|
||||
} else {
|
||||
|
||||
65
json_util.c
65
json_util.c
@@ -17,6 +17,7 @@
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
@@ -48,6 +49,7 @@
|
||||
#include "bits.h"
|
||||
#include "debug.h"
|
||||
#include "printbuf.h"
|
||||
#include "json_inttypes.h"
|
||||
#include "json_object.h"
|
||||
#include "json_tokener.h"
|
||||
#include "json_util.h"
|
||||
@@ -120,3 +122,66 @@ int json_object_to_file(char *filename, struct json_object *obj)
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_parse_int64(const char *buf, int64_t *retval)
|
||||
{
|
||||
int64_t num64;
|
||||
if (sscanf(buf, "%" SCNd64, &num64) != 1)
|
||||
{
|
||||
printf("Failed to parse, sscanf != 1\n");
|
||||
return 1;
|
||||
}
|
||||
const char *buf_skip_space = buf;
|
||||
int orig_has_neg = 0;
|
||||
// Skip leading spaces
|
||||
while (isspace((int)*buf_skip_space) && *buf_skip_space)
|
||||
buf_skip_space++;
|
||||
if (*buf_skip_space == '-')
|
||||
{
|
||||
buf_skip_space++;
|
||||
orig_has_neg = 1;
|
||||
}
|
||||
// Skip leading zeros
|
||||
while (*buf_skip_space == '0' && *buf_skip_space)
|
||||
buf_skip_space++;
|
||||
|
||||
if (errno != ERANGE)
|
||||
{
|
||||
char buf_cmp[100];
|
||||
char *buf_cmp_start = buf_cmp;
|
||||
int recheck_has_neg = 0;
|
||||
snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);
|
||||
if (*buf_cmp_start == '-')
|
||||
{
|
||||
recheck_has_neg = 1;
|
||||
buf_cmp_start++;
|
||||
}
|
||||
// No need to skip leading spaces or zeros here.
|
||||
|
||||
int buf_cmp_len = strlen(buf_cmp_start);
|
||||
/**
|
||||
* If the sign is different, or
|
||||
* some of the digits are different, or
|
||||
* there is another digit present in the original string
|
||||
* then we NOT successfully parsed the value.
|
||||
*/
|
||||
if (orig_has_neg != recheck_has_neg ||
|
||||
strncmp(buf_skip_space, buf_cmp_start, strlen(buf_cmp_start)) != 0 ||
|
||||
(strlen(buf_skip_space) != buf_cmp_len &&
|
||||
isdigit(buf_skip_space[buf_cmp_len])
|
||||
)
|
||||
)
|
||||
{
|
||||
errno = ERANGE;
|
||||
}
|
||||
}
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
if (orig_has_neg)
|
||||
num64 = INT64_MIN;
|
||||
else
|
||||
num64 = INT64_MAX;
|
||||
}
|
||||
*retval = num64;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
/* utility functions */
|
||||
extern struct json_object* json_object_from_file(const char *filename);
|
||||
extern int json_object_to_file(char *filename, struct json_object *obj);
|
||||
extern int json_parse_int64(const char *buf, int64_t *retval);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
12
parse_int64.test
Normal file
12
parse_int64.test
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Common definitions
|
||||
if test -z "$srcdir"; then
|
||||
srcdir="${0%/*}"
|
||||
test "$srcdir" = "$0" && srcdir=.
|
||||
test -z "$srcdir" && srcdir=.
|
||||
fi
|
||||
. "$srcdir/test-defs.sh"
|
||||
|
||||
run_output_test test_parse_int64
|
||||
exit $?
|
||||
114
test-defs.sh
Normal file
114
test-defs.sh
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
#! /bin/sh
|
||||
|
||||
# Make sure srcdir is an absolute path. Supply the variable
|
||||
# if it does not exist. We want to be able to run the tests
|
||||
# stand-alone!!
|
||||
#
|
||||
srcdir=${srcdir-.}
|
||||
if test ! -d $srcdir ; then
|
||||
echo "test-defs.sh: installation error" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use absolute paths
|
||||
case "$srcdir" in
|
||||
/* | [A-Za-z]:\\*) ;;
|
||||
*) srcdir=`\cd $srcdir && pwd` ;;
|
||||
esac
|
||||
|
||||
case "$top_builddir" in
|
||||
/* | [A-Za-z]:\\*) ;;
|
||||
*) top_builddir=`\cd ${top_builddir-..} && pwd` ;;
|
||||
esac
|
||||
|
||||
progname=`echo "$0" | sed 's,^.*/,,'`
|
||||
testname=`echo "$progname" | sed 's,-.*$,,'`
|
||||
testsubdir=${testsubdir-testSubDir}
|
||||
|
||||
# User can set VERBOSE to cause output redirection
|
||||
case "$VERBOSE" in
|
||||
[Nn]|[Nn][Oo]|0|"")
|
||||
VERBOSE=0
|
||||
exec > /dev/null 2>&1
|
||||
;;
|
||||
[Yy]|[Yy][Ee][Ss])
|
||||
VERBOSE=1
|
||||
;;
|
||||
esac
|
||||
|
||||
rm -rf "$testsubdir/$progname" > /dev/null 2>&1
|
||||
mkdir -p "$testsubdir/$progname"
|
||||
cd "$testsubdir/$progname" \
|
||||
|| { echo "Cannot make or change into $testsubdir/$progname"; exit 1; }
|
||||
|
||||
echo "=== Running test $progname"
|
||||
|
||||
CMP="${CMP-cmp}"
|
||||
|
||||
use_valgrind=${USE_VALGRIND-1}
|
||||
valgrind_path=$(which valgrind 2> /dev/null)
|
||||
if [ -z "${valgrind_path}" -o ! -x "${valgrind_path}" ] ; then
|
||||
use_valgrind=0
|
||||
fi
|
||||
|
||||
#
|
||||
# This is a common function to check the results of a test program
|
||||
# that is intended to generate consistent output across runs.
|
||||
#
|
||||
# ${top_builddir} must be set to the top level build directory.
|
||||
#
|
||||
# Output will be written to the current directory.
|
||||
#
|
||||
# It must be passed the name of the test command to run, which must be present
|
||||
# in the ${top_builddir} directory.
|
||||
#
|
||||
# It will compare the output of running that against <name of command>.expected
|
||||
#
|
||||
run_output_test()
|
||||
{
|
||||
TEST_COMMAND="$1"
|
||||
|
||||
REDIR_OUTPUT="> \"${TEST_COMMAND}.out\""
|
||||
if [ $VERBOSE -gt 1 ] ; then
|
||||
REDIR_OUTPUT="| tee \"${TEST_COMMAND}.out\""
|
||||
fi
|
||||
|
||||
if [ $use_valgrind -eq 1 ] ; then
|
||||
eval valgrind --tool=memcheck \
|
||||
--trace-children=yes \
|
||||
--demangle=yes \
|
||||
--log-file=vg.out \
|
||||
--leak-check=full \
|
||||
--show-reachable=yes \
|
||||
--run-libc-freeres=yes \
|
||||
"\"${top_builddir}/${TEST_COMMAND}\"" ${REDIR_OUTPUT}
|
||||
err=$?
|
||||
|
||||
else
|
||||
eval "\"${top_builddir}/${TEST_COMMAND}"\" ${REDIR_OUTPUT}
|
||||
err=$?
|
||||
fi
|
||||
|
||||
if [ $err -ne 0 ] ; then
|
||||
echo "ERROR: ${TEST_COMMAND} exited with non-zero exit status: $err" 1>&2
|
||||
fi
|
||||
|
||||
if [ $use_valgrind -eq 1 ] ; then
|
||||
if ! tail -1 "vg.out" | grep -q "ERROR SUMMARY: 0 errors" ; then
|
||||
echo "ERROR: valgrind found errors during execution:" 1>&2
|
||||
cat vg.out
|
||||
err=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! "$CMP" -s "${top_builddir}/${TEST_COMMAND}.expected" "${TEST_COMMAND}.out" ; then
|
||||
echo "ERROR: ${TEST_COMMAND} failed:" 1>&2
|
||||
diff "${top_builddir}/${TEST_COMMAND}.expected" "${TEST_COMMAND}.out" 1>&2
|
||||
err=1
|
||||
fi
|
||||
|
||||
return $err
|
||||
}
|
||||
|
||||
|
||||
2
test1.c
2
test1.c
@@ -158,7 +158,7 @@ int main(int argc, char **argv)
|
||||
json_object_put(my_string);
|
||||
json_object_put(my_int);
|
||||
json_object_put(my_object);
|
||||
//json_object_put(my_array);
|
||||
json_object_put(my_array);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
44
test1.expected
Normal file
44
test1.expected
Normal file
@@ -0,0 +1,44 @@
|
||||
my_string=
|
||||
my_string.to_string()="\t"
|
||||
my_string=\
|
||||
my_string.to_string()="\\"
|
||||
my_string=foo
|
||||
my_string.to_string()="foo"
|
||||
my_int=9
|
||||
my_int.to_string()=9
|
||||
my_array=
|
||||
[0]=1
|
||||
[1]=2
|
||||
[2]=3
|
||||
[3]=null
|
||||
[4]=5
|
||||
my_array.to_string()=[ 1, 2, 3, null, 5 ]
|
||||
my_object=
|
||||
abc: 12
|
||||
foo: "bar"
|
||||
bool0: false
|
||||
bool1: true
|
||||
my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true }
|
||||
new_obj.to_string()="\u0003"
|
||||
new_obj.to_string()="foo"
|
||||
new_obj.to_string()="foo"
|
||||
new_obj.to_string()="ABC"
|
||||
new_obj.to_string()=null
|
||||
new_obj.to_string()=true
|
||||
new_obj.to_string()=12
|
||||
new_obj.to_string()=12.300000
|
||||
new_obj.to_string()=[ "\n" ]
|
||||
new_obj.to_string()=[ "\nabc\n" ]
|
||||
new_obj.to_string()=[ null ]
|
||||
new_obj.to_string()=[ ]
|
||||
new_obj.to_string()=[ false ]
|
||||
new_obj.to_string()=[ "abc", null, "def", 12 ]
|
||||
new_obj.to_string()={ }
|
||||
new_obj.to_string()={ "foo": "bar" }
|
||||
new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true }
|
||||
new_obj.to_string()={ "foo": [ null, "foo" ] }
|
||||
new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] }
|
||||
got error as expected
|
||||
got error as expected
|
||||
got error as expected
|
||||
new_obj.to_string()={ "foo": { "bar": 13 } }
|
||||
12
test1.test
Normal file
12
test1.test
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Common definitions
|
||||
if test -z "$srcdir"; then
|
||||
srcdir="${0%/*}"
|
||||
test "$srcdir" = "$0" && srcdir=.
|
||||
test -z "$srcdir" && srcdir=.
|
||||
fi
|
||||
. "$srcdir/test-defs.sh"
|
||||
|
||||
run_output_test test1
|
||||
exit $?
|
||||
1
test2.expected
Normal file
1
test2.expected
Normal file
@@ -0,0 +1 @@
|
||||
new_obj.to_string()={ "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" ] } ] } } }
|
||||
12
test2.test
Normal file
12
test2.test
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Common definitions
|
||||
if test -z "$srcdir"; then
|
||||
srcdir="${0%/*}"
|
||||
test "$srcdir" = "$0" && srcdir=.
|
||||
test -z "$srcdir" && srcdir=.
|
||||
fi
|
||||
. "$srcdir/test-defs.sh"
|
||||
|
||||
run_output_test test2
|
||||
exit $?
|
||||
17
test4.c
17
test4.c
@@ -4,11 +4,14 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <json/json_object.h>
|
||||
#include <json/json_tokener.h>
|
||||
#include "config.h"
|
||||
|
||||
void print_hex( const unsigned char* s) {
|
||||
const unsigned char *iter = s;
|
||||
#include "json_inttypes.h"
|
||||
#include "json_object.h"
|
||||
#include "json_tokener.h"
|
||||
|
||||
void print_hex( const char* s) {
|
||||
const char *iter = s;
|
||||
unsigned char ch;
|
||||
while ((ch = *iter++) != 0) {
|
||||
if( ',' != ch)
|
||||
@@ -28,10 +31,10 @@ int main() {
|
||||
printf("input: %s\n", input);
|
||||
|
||||
int strings_match = !strcmp( expected, unjson);
|
||||
int retval = 0;
|
||||
if (strings_match) {
|
||||
printf("JSON parse result is correct: %s\n", unjson);
|
||||
printf("PASS\n");
|
||||
return(0);
|
||||
} else {
|
||||
printf("JSON parse result doesn't match expected string\n");
|
||||
printf("expected string bytes: ");
|
||||
@@ -39,6 +42,8 @@ int main() {
|
||||
printf("parsed string bytes: ");
|
||||
print_hex( unjson);
|
||||
printf("FAIL\n");
|
||||
return(1);
|
||||
retval = 1;
|
||||
}
|
||||
json_object_put(parse_result);
|
||||
return retval;
|
||||
}
|
||||
|
||||
3
test4.expected
Normal file
3
test4.expected
Normal file
@@ -0,0 +1,3 @@
|
||||
input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27"
|
||||
JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧
|
||||
PASS
|
||||
12
test4.test
Normal file
12
test4.test
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Common definitions
|
||||
if test -z "$srcdir"; then
|
||||
srcdir="${0%/*}"
|
||||
test "$srcdir" = "$0" && srcdir=.
|
||||
test -z "$srcdir" && srcdir=.
|
||||
fi
|
||||
. "$srcdir/test-defs.sh"
|
||||
|
||||
run_output_test test4
|
||||
exit $?
|
||||
99
test_parse_int64.c
Normal file
99
test_parse_int64.c
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "json_inttypes.h"
|
||||
#include "json_util.h"
|
||||
|
||||
void checkit(const char *buf)
|
||||
{
|
||||
int64_t cint64 = -666;
|
||||
|
||||
int retval = json_parse_int64(buf, &cint64);
|
||||
printf("buf=%s parseit=%d, value=%" PRId64 " \n", buf, retval, cint64);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test calls json_parse_int64 with a variety of different strings.
|
||||
* It's purpose is to ensure that the results are consistent across all
|
||||
* different environments that it might be executed in.
|
||||
*
|
||||
* This always exits with a 0 exit value. The output should be compared
|
||||
* against previously saved expected output.
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
checkit("x");
|
||||
|
||||
checkit("1");
|
||||
|
||||
strcpy(buf, "2147483647"); // aka INT32_MAX
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-1");
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, " -1");
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "00001234");
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "0001234x");
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-00001234");
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-00001234x");
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "4294967295"); // aka UINT32_MAX
|
||||
|
||||
sprintf(buf, "4294967296"); // aka UINT32_MAX + 1
|
||||
|
||||
strcpy(buf, "21474836470"); // INT32_MAX * 10
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "31474836470"); // INT32_MAX * 10 + a bunch
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-2147483647"); // INT32_MIN + 1
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-2147483648"); // INT32_MIN
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-2147483649"); // INT32_MIN - 1
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-21474836480"); // INT32_MIN * 10
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "9223372036854775807"); // INT64_MAX
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "9223372036854775808"); // INT64_MAX + 1
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-9223372036854775808"); // INT64_MIN
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-9223372036854775809"); // INT64_MIN - 1
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "18446744073709551615"); // UINT64_MAX
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "18446744073709551616"); // UINT64_MAX + 1
|
||||
checkit(buf);
|
||||
|
||||
strcpy(buf, "-18446744073709551616"); // -UINT64_MAX
|
||||
checkit(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
23
test_parse_int64.expected
Normal file
23
test_parse_int64.expected
Normal file
@@ -0,0 +1,23 @@
|
||||
Failed to parse, sscanf != 1
|
||||
buf=x parseit=1, value=-666
|
||||
buf=1 parseit=0, value=1
|
||||
buf=2147483647 parseit=0, value=2147483647
|
||||
buf=-1 parseit=0, value=-1
|
||||
buf= -1 parseit=0, value=-1
|
||||
buf=00001234 parseit=0, value=1234
|
||||
buf=0001234x parseit=0, value=1234
|
||||
buf=-00001234 parseit=0, value=-1234
|
||||
buf=-00001234x parseit=0, value=-1234
|
||||
buf=21474836470 parseit=0, value=21474836470
|
||||
buf=31474836470 parseit=0, value=31474836470
|
||||
buf=-2147483647 parseit=0, value=-2147483647
|
||||
buf=-2147483648 parseit=0, value=-2147483648
|
||||
buf=-2147483649 parseit=0, value=-2147483649
|
||||
buf=-21474836480 parseit=0, value=-21474836480
|
||||
buf=9223372036854775807 parseit=0, value=9223372036854775807
|
||||
buf=9223372036854775808 parseit=0, value=9223372036854775807
|
||||
buf=-9223372036854775808 parseit=0, value=-9223372036854775808
|
||||
buf=-9223372036854775809 parseit=0, value=-9223372036854775808
|
||||
buf=18446744073709551615 parseit=0, value=9223372036854775807
|
||||
buf=18446744073709551616 parseit=0, value=9223372036854775807
|
||||
buf=-18446744073709551616 parseit=0, value=-9223372036854775808
|
||||
Reference in New Issue
Block a user