]> granicus.if.org Git - json-c/commitdiff
* Add int64 support. Two new functions json_object_net_int64 and
authorMichael Clark <michael@metaparadigm.com>
Wed, 6 Oct 2010 16:39:20 +0000 (16:39 +0000)
committerMichael Clark <michael@metaparadigm.com>
Wed, 6 Oct 2010 16:39:20 +0000 (16:39 +0000)
    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

23 files changed:
ChangeLog
Doxyfile
Makefile.am
config.h.in
json_inttypes.h [new file with mode: 0644]
json_object.c
json_object.h
json_object_private.h
json_tokener.c
json_util.c
json_util.h
parse_int64.test [new file with mode: 0644]
test-defs.sh [new file with mode: 0644]
test1.c
test1.expected [new file with mode: 0644]
test1.test [new file with mode: 0644]
test2.expected [new file with mode: 0644]
test2.test [new file with mode: 0644]
test4.c
test4.expected [new file with mode: 0644]
test4.test [new file with mode: 0644]
test_parse_int64.c [new file with mode: 0644]
test_parse_int64.expected [new file with mode: 0644]

index 2011cc2eacf1da3ff975d42b37704f314233a0aa..6105c8e1b64fb4d6cec2fd6cc908150e52c6b9dd 100644 (file)
--- 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
index 7e5f306df3ea241957832f887ac5be6b08addb6c..3ff27eb191365bc220803006205fdd1a3e3ecd04 100644 (file)
--- 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. 
index 1c1a9badf7a6ea379efd3d533dd1eaf5947c482c..dc920f896e10eec10f8087554c61bb5f770a9362 100644 (file)
@@ -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)
+
index 5139ae8c5c311edc53e452b36ed363b9fbdae52e..83ab7973a8c22891a9f950e062aed77d62dcd544 100644 (file)
 /* 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
 
 /* 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 (file)
index 0000000..1cbafc2
--- /dev/null
@@ -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
index f52445c901163e2da6fb015d1d30767ce02393b0..c2b6fe2c885a70d221c6168c6b5fba0e84a3bdb7 100644 (file)
 #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:
index 80d23134f72a96c4e9e1f399b279905be37881e3..cea4c81064dba3f0e0907aa201ee17ddd5a05536 100644 (file)
@@ -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 */
index 9fb4011c8c8a33d9d4b58649cb3c55a1c717c80c..a0f98456c9496ad8a5696fa0055db5dcb2898ec1 100644 (file)
@@ -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;
index 8d0b5dce0e76d3aba33d32296d39820dcc3aaa3a..dbaacaa99d3e8c08f27e353c74cc8d2ee034762b 100644 (file)
 #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;
index 06e4a71c98c8b26f34167255c43e22f0baffcde8..e5a9dc6cd5cfc6019ec19cea9e8959551560d8cc 100644 (file)
@@ -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;
+}
index 134390f6bed5c9eab509f6f61164f804a0f2b877..fbfcb14eb5dbb7d35de4f168829cb443ee5b800b 100644 (file)
@@ -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 (file)
index 0000000..2b7fbfb
--- /dev/null
@@ -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 (file)
index 0000000..2014b37
--- /dev/null
@@ -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 d2e6d0b6868ab4c949e2f36684ad9bac79c59d1f..a3cc6d9753ef4b74ab33994d83ae1340058ea1d1 100644 (file)
--- 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 (file)
index 0000000..e38ef50
--- /dev/null
@@ -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 (file)
index 0000000..6074fac
--- /dev/null
@@ -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 (file)
index 0000000..0b740a9
--- /dev/null
@@ -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 (file)
index 0000000..cbb3830
--- /dev/null
@@ -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 921383dd51242c43bfeaebf8dbeb2502c56d4cdb..555afd1404196b7f72ecc5c8bf66081387df77b2 100644 (file)
--- 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 (file)
index 0000000..68d4336
--- /dev/null
@@ -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 (file)
index 0000000..8bcc460
--- /dev/null
@@ -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 (file)
index 0000000..42d4575
--- /dev/null
@@ -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 (file)
index 0000000..2d01ca7
--- /dev/null
@@ -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