summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Clark <michael@metaparadigm.com>2010-10-06 16:39:20 +0000
committerMichael Clark <michael@metaparadigm.com>2010-10-06 16:39:20 +0000
commitc4dceae1c53bc37cacc46a806f8a02524d12a382 (patch)
treec10fe3348cc8ff3ddee17f4cae386cbe2e5421a6
parent88ded9ceb8296eb6661c4d6f8f266ac74d81b9c4 (diff)
downloadjson-c-c4dceae1c53bc37cacc46a806f8a02524d12a382.tar.gz
* 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
-rw-r--r--ChangeLog4
-rw-r--r--Doxyfile2
-rw-r--r--Makefile.am32
-rw-r--r--config.h.in6
-rw-r--r--json_inttypes.h21
-rw-r--r--json_object.c72
-rw-r--r--json_object.h28
-rw-r--r--json_object_private.h3
-rw-r--r--json_tokener.c24
-rw-r--r--json_util.c65
-rw-r--r--json_util.h1
-rw-r--r--parse_int64.test12
-rw-r--r--test-defs.sh114
-rw-r--r--test1.c2
-rw-r--r--test1.expected44
-rw-r--r--test1.test12
-rw-r--r--test2.expected1
-rw-r--r--test2.test12
-rw-r--r--test4.c17
-rw-r--r--test4.expected3
-rw-r--r--test4.test12
-rw-r--r--test_parse_int64.c99
-rw-r--r--test_parse_int64.expected23
23 files changed, 569 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 2011cc2..6105c8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/Doxyfile b/Doxyfile
index 7e5f306..3ff27eb 100644
--- a/Doxyfile
+++ b/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.
diff --git a/Makefile.am b/Makefile.am
index 1c1a9ba..dc920f8 100644
--- a/Makefile.am
+++ b/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_object_private.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)
+
diff --git a/config.h.in b/config.h.in
index 5139ae8..83ab797 100644
--- a/config.h.in
+++ b/config.h.in
@@ -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
diff --git a/json_inttypes.h b/json_inttypes.h
new file mode 100644
index 0000000..1cbafc2
--- /dev/null
+++ b/json_inttypes.h
@@ -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
diff --git a/json_object.c b/json_object.c
index f52445c..c2b6fe2 100644
--- a/json_object.c
+++ b/json_object.c
@@ -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 (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:
diff --git a/json_object.h b/json_object.h
index 80d2313..cea4c81 100644
--- a/json_object.h
+++ b/json_object.h
@@ -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 */
diff --git a/json_object_private.h b/json_object_private.h
index 9fb4011..a0f9845 100644
--- a/json_object_private.h
+++ b/json_object_private.h
@@ -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;
diff --git a/json_tokener.c b/json_tokener.c
index 8d0b5dc..dbaacaa 100644
--- a/json_tokener.c
+++ b/json_tokener.c
@@ -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,11 +544,21 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
printbuf_memappend_fast(tok->pb, case_start, case_len);
}
{
- int numi;
- double numd;
- if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
- current = json_object_new_int(numi);
- } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
+ int64_t num64;
+ double numd;
+ 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 {
tok->err = json_tokener_error_parse_number;
diff --git a/json_util.c b/json_util.c
index 06e4a71..e5a9dc6 100644
--- a/json_util.c
+++ b/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;
+}
diff --git a/json_util.h b/json_util.h
index 134390f..fbfcb14 100644
--- a/json_util.h
+++ b/json_util.h
@@ -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
}
diff --git a/parse_int64.test b/parse_int64.test
new file mode 100644
index 0000000..2b7fbfb
--- /dev/null
+++ b/parse_int64.test
@@ -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 $?
diff --git a/test-defs.sh b/test-defs.sh
new file mode 100644
index 0000000..2014b37
--- /dev/null
+++ b/test-defs.sh
@@ -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
+}
+
+
diff --git a/test1.c b/test1.c
index d2e6d0b..a3cc6d9 100644
--- a/test1.c
+++ b/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;
}
diff --git a/test1.expected b/test1.expected
new file mode 100644
index 0000000..e38ef50
--- /dev/null
+++ b/test1.expected
@@ -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 } }
diff --git a/test1.test b/test1.test
new file mode 100644
index 0000000..6074fac
--- /dev/null
+++ b/test1.test
@@ -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 $?
diff --git a/test2.expected b/test2.expected
new file mode 100644
index 0000000..0b740a9
--- /dev/null
+++ b/test2.expected
@@ -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" ] } ] } } }
diff --git a/test2.test b/test2.test
new file mode 100644
index 0000000..cbb3830
--- /dev/null
+++ b/test2.test
@@ -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 $?
diff --git a/test4.c b/test4.c
index 921383d..555afd1 100644
--- a/test4.c
+++ b/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;
}
diff --git a/test4.expected b/test4.expected
new file mode 100644
index 0000000..68d4336
--- /dev/null
+++ b/test4.expected
@@ -0,0 +1,3 @@
+input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27"
+JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧
+PASS
diff --git a/test4.test b/test4.test
new file mode 100644
index 0000000..8bcc460
--- /dev/null
+++ b/test4.test
@@ -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 $?
diff --git a/test_parse_int64.c b/test_parse_int64.c
new file mode 100644
index 0000000..42d4575
--- /dev/null
+++ b/test_parse_int64.c
@@ -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;
+}
diff --git a/test_parse_int64.expected b/test_parse_int64.expected
new file mode 100644
index 0000000..2d01ca7
--- /dev/null
+++ b/test_parse_int64.expected
@@ -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