Hello community,

here is the log from the commit of package libfastjson for openSUSE:Factory 
checked in at 2017-11-16 13:58:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libfastjson (Old)
 and      /work/SRC/openSUSE:Factory/.libfastjson.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libfastjson"

Thu Nov 16 13:58:53 2017 rev:7 rq:541839 version:0.99.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/libfastjson/libfastjson.changes  2017-08-12 
19:33:26.424133581 +0200
+++ /work/SRC/openSUSE:Factory/.libfastjson.new/libfastjson.changes     
2017-11-16 13:58:56.870118451 +0100
@@ -1,0 +2,7 @@
+Tue Nov 14 14:45:51 UTC 2017 - [email protected]
+
+- update to 0.99.7:
+  * add option for case-insensitive comparisons
+  * Remove userdata and custom-serialization functions
+
+-------------------------------------------------------------------

Old:
----
  libfastjson-0.99.6.tar.gz

New:
----
  libfastjson-0.99.7.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libfastjson.spec ++++++
--- /var/tmp/diff_new_pack.jQ56oa/_old  2017-11-16 13:58:57.918080480 +0100
+++ /var/tmp/diff_new_pack.jQ56oa/_new  2017-11-16 13:58:57.918080480 +0100
@@ -18,7 +18,7 @@
 
 %define somajor 4
 Name:           libfastjson
-Version:        0.99.6
+Version:        0.99.7
 Release:        0
 Summary:        Fast JSON parsing library, a fork of json-c
 License:        MIT

++++++ libfastjson-0.99.6.tar.gz -> libfastjson-0.99.7.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/ChangeLog 
new/libfastjson-0.99.7/ChangeLog
--- old/libfastjson-0.99.6/ChangeLog    2017-05-11 16:09:47.000000000 +0200
+++ new/libfastjson-0.99.7/ChangeLog    2017-10-16 11:38:52.000000000 +0200
@@ -1,6 +1,35 @@
-0.99.6 2017-05-12
+0.99.7 2017-10-17
+- added option for case-insensitive comparisons
+  This permits to search for json keys in a case-sensitive way.
+  The default is "off", as this is against the JSON spec. However,
+  rsyslog needs this capability to increase usability inside the
+  variable system.
+  We add a new API call to switch between case-sensitive and
+  case-insensitive comparison, with case-sensitive being the default.
+  closes https://github.com/rsyslog/libfastjson/issues/142
+- Removed userdata and custom-serialization functions
+  Reasoning (from pull request):
+  The library uses the concept of "userdata" and "custom serialization
+  functions" that can be set from user space. However, to effectively
+  make use of this feature, a user must have a deep understanding of
+  the internal data representation of the library, which makes this
+  feature not very useful.
+  But what is worse: internally, the library itself also sometimes
+  assigns data to this userdata member (especially when working with
+  doubles), and it also sometimes assigns alternative serialization
+  functions. This makes the feature even more unusable, because as a
+  user you never can know when the userdata pointer is save to use
+  for your own settings, and when you must leave it alone because
+  it is used by the library.
+  Long story short. In this pull request I got rid of the userdata
+  pointer completely. The case where the library was using the
+  "userdata" (for storing the original string representation of a
+  parsed double) has been moved into the union that is already used
+  for storing values.
+  see also: https://github.com/rsyslog/libfastjson/pull/141
+  Thanks to Emiel Bruijntjes for the patch.
+0.99.6 2017-06-19
 - fix a build issue under Solaris
-
 0.99.5 2017-05-03
 - fix tautology comparison in tautology in `fjson_object_iter_equal`
 - made build under Solaris again
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/Makefile.am 
new/libfastjson-0.99.7/Makefile.am
--- old/libfastjson-0.99.6/Makefile.am  2017-05-11 15:25:57.000000000 +0200
+++ new/libfastjson-0.99.7/Makefile.am  2017-10-16 11:41:24.000000000 +0200
@@ -23,7 +23,7 @@
 # info on version-info:
 # 
http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
 libfastjson_la_LDFLAGS = \
-       -version-info 5:0:1 \
+       -version-info 6:0:2 \
        -export-symbols-regex '^fjson_.*' \
        -no-undefined \
        @JSON_BSYMBOLIC_LDFLAGS@
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/Makefile.in 
new/libfastjson-0.99.7/Makefile.in
--- old/libfastjson-0.99.6/Makefile.in  2017-05-11 16:11:06.000000000 +0200
+++ new/libfastjson-0.99.7/Makefile.in  2017-10-16 11:43:17.000000000 +0200
@@ -437,7 +437,7 @@
 # info on version-info:
 # 
http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
 libfastjson_la_LDFLAGS = \
-       -version-info 5:0:1 \
+       -version-info 6:0:2 \
        -export-symbols-regex '^fjson_.*' \
        -no-undefined \
        @JSON_BSYMBOLIC_LDFLAGS@
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/configure 
new/libfastjson-0.99.7/configure
--- old/libfastjson-0.99.6/configure    2017-05-11 16:11:06.000000000 +0200
+++ new/libfastjson-0.99.7/configure    2017-10-16 11:43:18.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libfastjson 0.99.6.
+# Generated by GNU Autoconf 2.69 for libfastjson 0.99.7.
 #
 # Report bugs to <[email protected]>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='libfastjson'
 PACKAGE_TARNAME='libfastjson'
-PACKAGE_VERSION='0.99.6'
-PACKAGE_STRING='libfastjson 0.99.6'
+PACKAGE_VERSION='0.99.7'
+PACKAGE_STRING='libfastjson 0.99.7'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1336,7 +1336,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libfastjson 0.99.6 to adapt to many kinds of systems.
+\`configure' configures libfastjson 0.99.7 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1407,7 +1407,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libfastjson 0.99.6:";;
+     short | recursive ) echo "Configuration of libfastjson 0.99.7:";;
    esac
   cat <<\_ACEOF
 
@@ -1525,7 +1525,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libfastjson configure 0.99.6
+libfastjson configure 0.99.7
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1948,7 +1948,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libfastjson $as_me 0.99.6, which was
+It was created by libfastjson $as_me 0.99.7, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2838,7 +2838,7 @@
 
 # Define the identity of the package.
  PACKAGE='libfastjson'
- VERSION='0.99.6'
+ VERSION='0.99.7'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -14559,7 +14559,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libfastjson $as_me 0.99.6, which was
+This file was extended by libfastjson $as_me 0.99.7, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14625,7 +14625,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-libfastjson config.status 0.99.6
+libfastjson config.status 0.99.7
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/configure.ac 
new/libfastjson-0.99.7/configure.ac
--- old/libfastjson-0.99.6/configure.ac 2017-05-11 16:10:39.000000000 +0200
+++ new/libfastjson-0.99.7/configure.ac 2017-10-16 11:40:10.000000000 +0200
@@ -1,7 +1,7 @@
 AC_PREREQ(2.52)
 
 # Process this file with autoconf to produce a configure script.
-AC_INIT([libfastjson], [0.99.6], [[email protected]])
+AC_INIT([libfastjson], [0.99.7], [[email protected]])
 # AIXPORT START: Detect the underlying OS
 unamestr=$(uname)
 AM_CONDITIONAL([AIX], [test x$unamestr = xAIX])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/json.h 
new/libfastjson-0.99.7/json.h
--- old/libfastjson-0.99.6/json.h       2017-05-11 14:02:02.000000000 +0200
+++ new/libfastjson-0.99.7/json.h       2017-10-13 11:22:06.000000000 +0200
@@ -42,6 +42,19 @@
  * @param size new initial size for printbuf (formatting buffer)
  */
 extern void fjson_global_set_printbuf_initial_size(int size);
+
+/**
+ * Set case sensitive/insensitive comparison mode. If set to 0,
+ * comparisons for JSON keys will be case-insensitive. Otherwise,
+ * they will be case-sensitive.
+ * NOTE: the JSON standard demands case sensitivity. By turning
+ * this off, the JSON standard is not obeyed. Most importantly,
+ * if keys exists which only differ in case, only partial data
+ * access is possible. So use with care and only if you know
+ * exactly what you are doing!
+ */
+extern void fjson_global_do_case_sensitive_comparison(const int newval);
+
 /**
  * report the current libfastjson version
  */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/json_object.c 
new/libfastjson-0.99.7/json_object.c
--- old/libfastjson-0.99.6/json_object.c        2017-05-11 14:02:02.000000000 
+0200
+++ new/libfastjson-0.99.7/json_object.c        2017-10-16 11:33:40.000000000 
+0200
@@ -2,7 +2,7 @@
  * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
  * Michael Clark <[email protected]>
  * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
- * Copyright (c) 2015 Rainer Gerhards
+ * Copyright (c) 2015-2017 Rainer Gerhards
  *
  * This library is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See COPYING for details.
@@ -29,6 +29,7 @@
 #include "atomic.h"
 #include "printbuf.h"
 #include "arraylist.h"
+#include "json.h"
 #include "json_object.h"
 #include "json_object_private.h"
 #include "json_object_iterator.h"
@@ -55,6 +56,11 @@
 static fjson_object_to_json_string_fn fjson_object_string_to_json_string;
 static fjson_object_to_json_string_fn fjson_object_array_to_json_string;
 
+static int do_case_sensitive_comparison = 1;
+void fjson_global_do_case_sensitive_comparison(const int newval)
+{
+       do_case_sensitive_comparison = newval;
+}
 
 /* helper for accessing the optimized string data component in fjson_object
  */
@@ -190,8 +196,6 @@
        const int cnt = ATOMIC_DEC_AND_FETCH(&jso->_ref_count, 
&jso->_mut_ref_count);
        if(cnt > 0) return 0;
 
-       if (jso->_user_delete)
-               jso->_user_delete(jso, jso->_userdata);
        jso->_delete(jso);
        return 1;
 }
@@ -237,61 +241,6 @@
        return jso->o_type;
 }
 
-/* set a custom conversion to string */
-
-void fjson_object_set_serializer(fjson_object *jso,
-       fjson_object_to_json_string_fn to_string_func,
-       void *userdata,
-       fjson_object_delete_fn *user_delete)
-{
-       // First, clean up any previously existing user info
-       if (jso->_user_delete)
-       {
-               jso->_user_delete(jso, jso->_userdata);
-       }
-       jso->_userdata = NULL;
-       jso->_user_delete = NULL;
-
-       if (to_string_func == NULL)
-       {
-               // Reset to the standard serialization function
-               switch(jso->o_type)
-               {
-               case fjson_type_null:
-                       jso->_to_json_string = NULL;
-                       break;
-               case fjson_type_boolean:
-                       jso->_to_json_string = 
&fjson_object_boolean_to_json_string;
-                       break;
-               case fjson_type_double:
-                       jso->_to_json_string = 
&fjson_object_double_to_json_string;
-                       break;
-               case fjson_type_int:
-                       jso->_to_json_string = &fjson_object_int_to_json_string;
-                       break;
-               case fjson_type_object:
-                       jso->_to_json_string = 
&fjson_object_object_to_json_string;
-                       break;
-               case fjson_type_array:
-                       jso->_to_json_string = 
&fjson_object_array_to_json_string;
-                       break;
-               case fjson_type_string:
-                       jso->_to_json_string = 
&fjson_object_string_to_json_string;
-                       break;
-               default:
-                       /* this should NOT HAPPEN! */
-                       jso->_to_json_string = NULL;
-                       break;
-               }
-               return;
-       }
-
-       jso->_to_json_string = to_string_func;
-       jso->_userdata = userdata;
-       jso->_user_delete = user_delete;
-}
-
-
 /* extended conversion to string */
 
 const char* fjson_object_to_json_string_ext(struct fjson_object *jso, int 
flags)
@@ -335,8 +284,8 @@
 /* fjson_object_object */
 
 static int fjson_object_object_to_json_string(struct fjson_object* jso,
-                                            struct printbuf *pb,
-                                            int level,
+                                                struct printbuf *pb,
+                                                int level,
                                                 int flags)
 {
        struct fjson_object *val;
@@ -427,8 +376,13 @@
        struct fjson_object_iterator it = fjson_object_iter_begin(jso);
        struct fjson_object_iterator itEnd = fjson_object_iter_end(jso);
        while (!fjson_object_iter_equal(&it, &itEnd)) {
-               if (!strcmp (key, fjson_object_iter_peek_name(&it)))
-                       return _fjson_object_iter_peek_child(&it);
+               if (do_case_sensitive_comparison) {
+                       if (!strcmp (key, fjson_object_iter_peek_name(&it)))
+                               return _fjson_object_iter_peek_child(&it);
+               } else {
+                       if (!strcasecmp (key, fjson_object_iter_peek_name(&it)))
+                               return _fjson_object_iter_peek_child(&it);
+               }
                fjson_object_iter_next(&it);
        }
        return NULL;
@@ -570,8 +524,8 @@
 /* fjson_object_boolean */
 
 static int fjson_object_boolean_to_json_string(struct fjson_object* jso,
-                                             struct printbuf *pb,
-                                             int __attribute__((unused)) level,
+                                                 struct printbuf *pb,
+                                                 int __attribute__((unused)) 
level,
                                                  int __attribute__((unused)) 
flags)
 {
        if (jso->o.c_boolean)
@@ -602,7 +556,7 @@
        case fjson_type_int:
                return (jso->o.c_int64 != 0);
        case fjson_type_double:
-               return (jso->o.c_double != 0);
+               return (jso->o.c_double.value != 0);
        case fjson_type_string:
                return (jso->o.c_string.len != 0);
        case fjson_type_null:
@@ -665,7 +619,7 @@
                else
                        return (int32_t)cint64;
        case fjson_type_double:
-               return (int32_t)jso->o.c_double;
+               return (int32_t)jso->o.c_double.value;
        case fjson_type_boolean:
                return jso->o.c_boolean;
        case fjson_type_null:
@@ -698,7 +652,7 @@
        case fjson_type_int:
                return jso->o.c_int64;
        case fjson_type_double:
-               return (int64_t)jso->o.c_double;
+               return (int64_t)jso->o.c_double.value;
        case fjson_type_boolean:
                return jso->o.c_boolean;
        case fjson_type_string:
@@ -716,29 +670,35 @@
 /* fjson_object_double */
 
 static int fjson_object_double_to_json_string(struct fjson_object* jso,
-                                            struct printbuf *pb,
-                                            int __attribute__((unused)) level,
+                                                struct printbuf *pb,
+                                                int __attribute__((unused)) 
level,
                                                 int __attribute__((unused)) 
flags)
 {
        char buf[128], *p, *q;
        int size;
        double dummy;  /* needed for modf() */
+       
+       if (jso->o.c_double.source) {
+               printbuf_memappend_no_nul(pb, jso->o.c_double.source, 
strlen(jso->o.c_double.source));
+               return 0; /* we need to keep compatible with the API */
+       }
+       
        /* Although JSON RFC does not support
         * NaN or Infinity as numeric values
         * ECMA 262 section 9.8.1 defines
         * how to handle these cases as strings
         */
-       if(isnan(jso->o.c_double))
+       if(isnan(jso->o.c_double.value))
                size = snprintf(buf, sizeof(buf), "NaN");
-       else if(isinf(jso->o.c_double))
-               if(jso->o.c_double > 0)
+       else if(isinf(jso->o.c_double.value))
+               if(jso->o.c_double.value > 0)
                        size = snprintf(buf, sizeof(buf), "Infinity");
                else
                        size = snprintf(buf, sizeof(buf), "-Infinity");
        else
                size = snprintf(buf, sizeof(buf),
-                       (modf(jso->o.c_double, &dummy)==0)?"%.17g.0":"%.17g",
-                       jso->o.c_double);
+                       (modf(jso->o.c_double.value, 
&dummy)==0)?"%.17g.0":"%.17g",
+                       jso->o.c_double.value);
 
        p = strchr(buf, ',');
        if (p) {
@@ -760,13 +720,20 @@
        return 0; /* we need to keep compatible with the API */
 }
 
+static void fjson_object_double_delete(struct fjson_object *jso)
+{
+       free(jso->o.c_double.source);
+       fjson_object_generic_delete(jso);
+}
+
 struct fjson_object* fjson_object_new_double(double d)
 {
        struct fjson_object *jso = fjson_object_new(fjson_type_double);
        if (!jso)
                return NULL;
        jso->_to_json_string = &fjson_object_double_to_json_string;
-       jso->o.c_double = d;
+       jso->o.c_double.value = d;
+       jso->o.c_double.source = NULL;
        return jso;
 }
 
@@ -776,31 +743,17 @@
        if (!jso)
                return NULL;
 
-       char *new_ds = strdup(ds);
-       if (!new_ds)
+       jso->o.c_double.source = strdup(ds);
+       if (!jso->o.c_double.source)
        {
                fjson_object_generic_delete(jso);
                errno = ENOMEM;
                return NULL;
        }
-       fjson_object_set_serializer(jso, fjson_object_userdata_to_json_string,
-           new_ds, fjson_object_free_userdata);
+       jso->_delete = &fjson_object_double_delete;
        return jso;
 }
 
-int fjson_object_userdata_to_json_string(struct fjson_object *jso,
-       struct printbuf *pb, int __attribute__((unused)) level, int 
__attribute__((unused)) flags)
-{
-       int userdata_len = strlen((const char *)jso->_userdata);
-       printbuf_memappend_no_nul(pb, (const char *)jso->_userdata, 
userdata_len);
-       return 0; /* we need to keep compatible with the API */
-}
-
-void fjson_object_free_userdata(struct fjson_object __attribute__((unused)) 
*jso, void *userdata)
-{
-       free(userdata);
-}
-
 double fjson_object_get_double(struct fjson_object *jso)
 {
        double cdouble;
@@ -809,7 +762,7 @@
        if(!jso) return 0.0;
        switch(jso->o_type) {
        case fjson_type_double:
-               return jso->o.c_double;
+               return jso->o.c_double.value;
        case fjson_type_int:
                return jso->o.c_int64;
        case fjson_type_boolean:
@@ -857,9 +810,9 @@
 /* fjson_object_string */
 
 static int fjson_object_string_to_json_string(struct fjson_object* jso,
-                                            struct printbuf *pb,
-                                            int __attribute__((unused)) level,
-                                            int __attribute__((unused)) flags)
+                                                struct printbuf *pb,
+                                                int __attribute__((unused)) 
level,
+                                                int __attribute__((unused)) 
flags)
 {
        printbuf_memappend_char(pb, '\"');
        fjson_escape_str(pb, get_string_component(jso));
@@ -1051,13 +1004,13 @@
 }
 
 int fjson_object_array_put_idx(struct fjson_object *jso, int idx,
-                             struct fjson_object *val)
+                                 struct fjson_object *val)
 {
        return array_list_put_idx(jso->o.c_array, idx, val);
 }
 
 struct fjson_object* fjson_object_array_get_idx(struct fjson_object *jso,
-                                             int idx)
+                                                 int idx)
 {
        return (struct fjson_object*)array_list_get_idx(jso->o.c_array, idx);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/json_object.h 
new/libfastjson-0.99.7/json_object.h
--- old/libfastjson-0.99.6/json_object.h        2017-05-11 14:02:02.000000000 
+0200
+++ new/libfastjson-0.99.7/json_object.h        2017-10-16 11:33:40.000000000 
+0200
@@ -133,19 +133,6 @@
  */
 typedef size_t (fjson_write_fn)(void *ptr, const char *buffer, size_t size);
 
-/**
- * Type of custom user delete functions.  See fjson_object_set_serializer.
- */
-typedef void (fjson_object_delete_fn)(struct fjson_object *jso, void 
*userdata);
-
-/**
- * Type of a custom serialization function.  See fjson_object_set_serializer.
- */
-typedef int (fjson_object_to_json_string_fn)(struct fjson_object *jso,
-                                               struct printbuf *pb,
-                                               int level,
-                                               int flags);
-
 /* supported object types */
 
 typedef enum fjson_type {
@@ -209,8 +196,25 @@
  */
 extern enum fjson_type fjson_object_get_type(struct fjson_object *obj);
 
+/**
+ * Get the size of the json string if it was dumped
+ * @param obj object to calculate the size of
+ * @returns the size of the json string
+ */
+extern size_t fjson_object_size(struct fjson_object *obj);
 
-/** Dump object to a user-supplied function.
+/**
+ * Extended version of the above function that accept a flags parameter 
identical
+ * to the fjson_object_dump_ext() function that you can use the specify how to
+ * format the string for which the size is calculated
+ * @param obj the object to calculate the size of
+ * @param flags extra flags
+ * @return size_t
+ */
+extern size_t fjson_object_size_ext(struct fjson_object *obj, int flags);
+
+/**
+ * Dump object to a user-supplied function.
  * Equivalent to fjson_object_write_ext(obj, FJSON_TO_STRING_SPACED, func, ptr)
  * @param obj object to be written
  * @param func your function that will be called to write the data
@@ -231,6 +235,28 @@
 extern size_t fjson_object_dump_ext(struct fjson_object *obj, int flags, 
fjson_write_fn *func, void *ptr);
 
 /**
+ * Dump function that uses a user-supplied temporary buffer for dumping the
+ * json. Both the above declared fjson_object_dump() and 
fjson_object_dump_ext()
+ * functions uses an internal buffer of 128 bytes that is first filled before
+ * the user-supplied function is called. This buffer prevents that many calls
+ * to the callback function are done for single quotes, comma's and curly
+ * braces. All these calls are first buffered and grouped into a single call
+ * to the user space function. However, since the buffer limit is somewhat
+ * arbitrary, you can also use this fjson_object_dump_buffered() function to
+ * use your own temporary buffer. Note that the buffer might be completely
+ * overwritten during the call to this function, and that the contents of the
+ * buffer are undefined after the call.
+ * @param obj object to be written
+ * @param flags extra flags
+ * @param temp your temporary buffer that is used to group calls
+ * @param size size of your temporary buffer
+ * @param func your function that will be called to write the data
+ * @param ptr pointer that will be passed as first argument to your function
+ */
+extern size_t fjson_object_dump_buffered(struct fjson_object *obj, int flags, 
char *temp,
+size_t size, fjson_write_fn *func, void *ptr);
+
+/**
  * Write the json tree to a file
  * Equivalent to fjson_object_write_ext(obj, FJSON_TO_STRING_SPACED, fp)
  * @param obj object to be written
@@ -268,57 +294,6 @@
 extern const char* fjson_object_to_json_string_ext(struct fjson_object *obj, 
int
 flags);
 
-/**
- * Set a custom serialization function to be used when this particular object
- * is converted to a string by fjson_object_to_json_string.
- *
- * If a custom serializer is already set on this object, any existing
- * user_delete function is called before the new one is set.
- *
- * If to_string_func is NULL, the other parameters are ignored
- * and the default behaviour is reset.
- *
- * The userdata parameter is optional and may be passed as NULL.  If provided,
- * it is passed to to_string_func as-is.  This parameter may be NULL even
- * if user_delete is non-NULL.
- *
- * The user_delete parameter is optional and may be passed as NULL, even if
- * the userdata parameter is non-NULL.  It will be called just before the
- * fjson_object is deleted, after it's reference count goes to zero
- * (see fjson_object_put()).
- * If this is not provided, it is up to the caller to free the userdata at
- * an appropriate time. (i.e. after the fjson_object is deleted)
- *
- * @param jso the object to customize
- * @param to_string_func the custom serialization function
- * @param userdata an optional opaque cookie
- * @param user_delete an optional function from freeing userdata
- */
-extern void fjson_object_set_serializer(fjson_object *jso,
-       fjson_object_to_json_string_fn to_string_func,
-       void *userdata,
-       fjson_object_delete_fn *user_delete);
-
-/**
- * Simply call free on the userdata pointer.
- * Can be used with fjson_object_set_serializer().
- *
- * @param jso unused
- * @param userdata the pointer that is passed to free().
- */
-fjson_object_delete_fn fjson_object_free_userdata;
-
-/**
- * Copy the jso->_userdata string over to pb as-is.
- * Can be used with fjson_object_set_serializer().
- *
- * @param jso The object whose _userdata is used.
- * @param pb The destination buffer.
- * @param level Ignored.
- * @param flags Ignored.
- */
-fjson_object_to_json_string_fn fjson_object_userdata_to_json_string;
-
 
 /* object type methods */
 
@@ -504,7 +479,7 @@
  * @param val the fjson_object to be added
  */
 extern int fjson_object_array_put_idx(struct fjson_object *obj, int idx,
-                                    struct fjson_object *val);
+                                        struct fjson_object *val);
 
 /** Get the element at specificed index of the array (a fjson_object of type 
fjson_type_array)
  * @param obj the fjson_object instance
@@ -512,7 +487,7 @@
  * @returns the fjson_object at the specified index (or NULL)
  */
 extern struct fjson_object* fjson_object_array_get_idx(struct fjson_object 
*obj,
-                                                    int idx);
+                                                        int idx);
 
 /* fjson_bool type methods */
 
@@ -596,7 +571,7 @@
 
 /**
  * Create a new fjson_object of type fjson_type_double, using
- * the exact serialized representation of the value.
+ * the exact representation of the value.
  *
  * This allows for numbers that would otherwise get displayed
  * inefficiently (e.g. 12.3 => "12.300000000000001") to be
@@ -605,13 +580,6 @@
  * Note: this is used by fjson_tokener_parse_ex() to allow for
  *   an exact re-serialization of a parsed object.
  *
- * An equivalent sequence of calls is:
- * @code
- *   jso = fjson_object_new_double(d);
- *   fjson_object_set_serializer(d, fjson_object_userdata_to_json_string,
- *       strdup(ds), fjson_object_free_userdata)
- * @endcode
- *
  * @param d the numeric value of the double.
  * @param ds the string representation of the double.  This will be copied.
  */
@@ -739,8 +707,6 @@
 #define json_object_object_add(a, b, c) fjson_object_object_add((a), (b), (c))
 #define json_object_object_add_ex fjson_object_object_add_ex
 #define json_object_object_get_ex fjson_object_object_get_ex
-#define json_object_object_foreach fjson_object_object_foreach
-#define json_object_object_foreachC fjson_object_object_foreachC
 #define json_object_object_get fjson_object_object_get
 #define json_object_object_del fjson_object_object_del
 #define json_object_new_array fjson_object_new_array
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/json_object_private.h 
new/libfastjson-0.99.7/json_object_private.h
--- old/libfastjson-0.99.6/json_object_private.h        2017-05-11 
14:02:02.000000000 +0200
+++ new/libfastjson-0.99.7/json_object_private.h        2017-10-16 
11:33:40.000000000 +0200
@@ -19,7 +19,14 @@
 
 #define LEN_DIRECT_STRING_DATA 32 /**< how many bytes are directly stored in 
fjson_object for strings? */
 
+/**
+ *  Type of the delete and serialization functions.
+ */
 typedef void (fjson_object_private_delete_fn)(struct fjson_object *o);
+typedef int (fjson_object_to_json_string_fn)(struct fjson_object *jso,
+                                               struct printbuf *pb,
+                                               int level,
+                                               int flags);
 
 struct _fjson_child {
        /**
@@ -50,7 +57,10 @@
        struct printbuf *_pb;
        union data {
                fjson_bool c_boolean;
-               double c_double;
+               struct {
+                       double value;
+                       char *source;
+               } c_double;
                int64_t c_int64;
                struct {
                        int nelem;
@@ -70,8 +80,6 @@
                int len;
                } c_string;
        } o;
-       fjson_object_delete_fn *_user_delete;
-       void *_userdata;
        DEF_ATOMIC_HELPER_MUT(_mut_ref_count)
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/json_print.c 
new/libfastjson-0.99.7/json_print.c
--- old/libfastjson-0.99.6/json_print.c 2017-05-11 14:02:02.000000000 +0200
+++ new/libfastjson-0.99.7/json_print.c 2017-10-16 11:33:40.000000000 +0200
@@ -20,6 +20,12 @@
 #include <string.h>
 #include <math.h>
 
+#ifdef HAVE_STDARG_H
+# include <stdarg.h>
+#else /* !HAVE_STDARG_H */
+# error Not enough var arg support!
+#endif /* HAVE_STDARG_H */
+
 #include "json_object.h"
 #include "json_object_private.h"
 #include "json_object_iterator.h"
@@ -29,9 +35,185 @@
 # error You do not have snprintf on your system.
 #endif /* HAVE_SNPRINTF */
 
+#if !defined(HAVE_VASPRINTF)
+/* CAW: compliant version of vasprintf */
+/* Note: on OpenCSW, we have vasprintf() inside the headers, but not inside 
the lib.
+ * So we need to use a different name, else we get issues with redefinitions. 
We
+ * we solve this by using the macro below, which just renames the function BUT
+ * does not affect the (variadic) arguments.
+ * rgerhards, 2017-04-11
+ */
+#define  vasprintf rs_vasprintf
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+static int rs_vasprintf(char **buf, const char *fmt, va_list ap)
+{
+       int chars;
+       char *b;
+       static char _T_emptybuffer = '\0';
+
+       if(!buf) { return -1; }
+
+       /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't 
overwrite
+          our buffer like on some 64bit sun systems.... but hey, its time to 
move on */
+       chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
+       if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this 
problem */
+
+       b = (char*)malloc(sizeof(char)*chars);
+       if(!b) { return -1; }
+
+       if((chars = vsprintf(b, fmt, ap)) < 0) {
+               free(b);
+       } else {
+               *buf = b;
+       }
+
+       return chars;
+}
+#pragma GCC diagnostic pop
+#endif /* !HAVE_VASPRINTF */
+
+/**
+ *  Internal structure that we use for buffering the print output
+ */
+struct buffer {
+       char *buffer;
+       size_t size;
+       size_t filled;
+       fjson_write_fn *overflow;
+       void *ptr;
+};
+
+/**
+ *  Internal method to flush the buffer
+ *  @param  buffer
+ *  @return size_t
+ */
+static size_t buffer_flush(struct buffer *buffer)
+{
+       // call the user-supplied overflow function
+       size_t result = buffer->overflow(buffer->ptr, buffer->buffer, 
buffer->filled);
+
+       // buffer is empty now
+       buffer->filled = 0;
+
+       // done
+       return result;
+}
+
+/**
+ *  Internal method to append data to the buffer
+ *  @param  buffer
+ *  @param  data
+ *  @param  size
+ *  @return size_t
+ */
+static size_t buffer_append(struct buffer *buffer, const char *data, size_t 
size)
+{
+       // return value
+       size_t result = 0;
+
+       // is the data to big to fit in the buffer?
+       if (buffer->filled + size > buffer->size)
+       {
+               // flush current buffer
+               if (buffer->filled > 0) result += buffer_flush(buffer);
+
+               // does it still not fit? then we pass it to the callback 
immediately
+               if (size > buffer->size) return result + 
buffer->overflow(buffer->ptr, data, size);
+       }
+
+       // append to the buffer
+       memcpy(buffer->buffer + buffer->filled, data, size);
+
+       // update buffer size
+       buffer->filled += size;
+
+       // done
+       return result;
+}
+
+/**
+ *  Internal method to printf() into the buffer
+ *  @param  buffer
+ *  @param  format
+ *  @param ...
+ *  @return size_t
+ */
+__attribute__((__format__(__printf__, 2, 3)))
+static size_t buffer_printf(struct buffer *buffer, const char *format, ...)
+{
+       // return value
+       size_t result = 0;
+
+       // variables used in this function
+       va_list arguments;
+       char *tmp;
+       int size;
+
+       // make sure we have sufficient room in our buffer
+       if (buffer->size - buffer->filled < 32) result += buffer_flush(buffer);
+
+       // initialize varargs
+       va_start(arguments, format);
+
+       // write to the buffer (note the extra char for the extra null that is 
written by vsnprintf())
+       size = vsnprintf(buffer->buffer + buffer->filled, buffer->size - 
buffer->filled - 1, format, arguments);
+
+       // clean up varargs (it is not possible to reuse the vararg arguments 
later on,
+       // the have to be reset and possible reinitialized later on)
+       va_end(arguments);
+
+       // was this all successful?
+       if (size >= 0 && size < (int)(buffer->size - buffer->filled))
+       {
+               // this was a major success
+               buffer->filled += size;
+       }
+       else if (size > 0 && size < (int)buffer->size)
+       {
+               // there was not enough room in the buffer, but it would have 
been enough if
+               // we would have been able to use the entire buffer, so we 
reset the buffer,
+               // and retry the whole procedure
+               result += buffer_flush(buffer);
+
+               // buffer is empty now, we can retry, start with the vararg 
initialization
+               va_start(arguments, format);
+
+               // format into the buffer, again
+               buffer->size += vsnprintf(buffer->buffer + buffer->filled, 
buffer->size - buffer->filled - 1, format, arguments);
+
+               // clean up varargs
+               va_end(arguments);
+       }
+       else
+       {
+               // initialize varargs
+               va_start(arguments, format);
+
+               // our own buffer is not big enough to fit the text, we are 
going to use
+               // a dynamically allocated buffer using vasprintf(), init 
varargs first
+               va_start(arguments, format);
+
+               // use dynamically allocated vasprintf() call
+               size = vasprintf(&tmp, format, arguments);
+
+               // clean up varargs
+               va_end(arguments);
+
+               // was this a success?
+               if (size > 0) result += buffer_append(buffer, tmp, size);
+
+               // deallocate the memory
+               if (size >= 0) free(tmp);
+       }
+
+       // done
+       return result;
+}
 
 /* Forward declaration of the write function */
-static size_t write(struct fjson_object *jso, int level, int flags, 
fjson_write_fn *func, void *ptr);
+static size_t write(struct fjson_object *jso, int level, int flags, struct 
buffer *buffer);
 
 /**
  *  helper for accessing the optimized string data component in fjson_object
@@ -80,45 +262,41 @@
 /**
  *  Function to escape a string
  *  @param  str     the string to be escaped
- *  @param  func    user supplied write function
- *  @param  ptr     user supplied pointer
+ *  @param  buffer  the internal buffer to write to
  *  @return size_t  number of bytes written
  */
-static size_t escape(const char *str, fjson_write_fn *func, void *ptr)
+static size_t escape(const char *str, struct buffer *buffer)
 {
-       int size;
-       char tempbuf[6];
        size_t result = 0;
        const char *start_offset = str;
        while(1) { /* broken below on 0-byte */
                if(char_needsEscape[*((unsigned char*)str)]) {
                        if(*str == '\0') break;
-                       if(str != start_offset) result += func(ptr, 
start_offset, str - start_offset);
+                       if(str != start_offset) result += buffer_append(buffer, 
start_offset, str - start_offset);
                        switch(*str) {
-                       case '\b':  result += func(ptr, "\\b", 2); break;
-                       case '\n':  result += func(ptr, "\\n", 2); break;
-                       case '\r':  result += func(ptr, "\\r", 2); break;
-                       case '\t':  result += func(ptr, "\\t", 2); break;
-                       case '\f':  result += func(ptr, "\\f", 2); break;
-                       case '"':   result += func(ptr, "\\\"", 2); break;
-                       case '\\':  result += func(ptr, "\\\\", 2); break;
-                       case '/':   result += func(ptr, "\\/", 2); break;
+                       case '\b':  result += buffer_append(buffer, "\\b", 2); 
break;
+                       case '\n':  result += buffer_append(buffer, "\\n", 2); 
break;
+                       case '\r':  result += buffer_append(buffer, "\\r", 2); 
break;
+                       case '\t':  result += buffer_append(buffer, "\\t", 2); 
break;
+                       case '\f':  result += buffer_append(buffer, "\\f", 2); 
break;
+                       case '"':   result += buffer_append(buffer, "\\\"", 2); 
break;
+                       case '\\':  result += buffer_append(buffer, "\\\\", 2); 
break;
+                       case '/':   result += buffer_append(buffer, "\\/", 2); 
break;
                        default:
-                               size = snprintf(tempbuf, sizeof(tempbuf), 
"\\u00%c%c", fjson_hex_chars[*str >> 4], fjson_hex_chars[*str & 0xf]);
-                               result += func(ptr, tempbuf, size);
+                               result += buffer_printf(buffer, "\\u00%c%c", 
fjson_hex_chars[*str >> 4], fjson_hex_chars[*str & 0xf]);
                                break;
                        }
                        start_offset = ++str;
                } else
                        ++str;
        }
-       if(str != start_offset) result += func(ptr, start_offset, str - 
start_offset);
+       if(str != start_offset) result += buffer_append(buffer, start_offset, 
str - start_offset);
        return result;
 }
 
 /* add indentation */
 
-static size_t indent(int level, int flags, fjson_write_fn *func, void *ptr)
+static size_t indent(int level, int flags, struct buffer *buffer)
 {
        // result variable, and loop counter
        size_t result = 0;
@@ -131,8 +309,8 @@
        for (i = 0; i < level; ++i)
        {
                // write a tab or two spaces
-               if (flags & FJSON_TO_STRING_PRETTY_TAB) result += func(ptr, 
"\t", 1);
-               else result += func(ptr, "  ", 2);
+               if (flags & FJSON_TO_STRING_PRETTY_TAB) result += 
buffer_append(buffer, "\t", 1);
+               else result += buffer_append(buffer, "  ", 2);
        }
 
        // done
@@ -141,86 +319,100 @@
 
 /* write a json object */
 
-static size_t write_object(struct fjson_object* jso, int level, int flags, 
fjson_write_fn *func, void *ptr)
+static size_t write_object(struct fjson_object* jso, int level, int flags, 
struct buffer *buffer)
 {
        int had_children = 0;
        size_t result = 0;
 
-       result += func(ptr, "{" /*}*/, 1);
-       if (flags & FJSON_TO_STRING_PRETTY) result += func(ptr, "\n", 1);
+       result += buffer_append(buffer, "{" /*}*/, 1);
+       if (flags & FJSON_TO_STRING_PRETTY) result += buffer_append(buffer, 
"\n", 1);
        struct fjson_object_iterator it = fjson_object_iter_begin(jso);
        struct fjson_object_iterator itEnd = fjson_object_iter_end(jso);
        while (!fjson_object_iter_equal(&it, &itEnd)) {
                if (had_children)
                {
-                       result += func(ptr, ",", 1);
-                       if (flags & FJSON_TO_STRING_PRETTY) result += func(ptr, 
"\n", 1);
+                       result += buffer_append(buffer, ",", 1);
+                       if (flags & FJSON_TO_STRING_PRETTY) result += 
buffer_append(buffer, "\n", 1);
                }
                had_children = 1;
-               if (flags & FJSON_TO_STRING_SPACED) result += func(ptr, " ", 1);
-               result += indent(level+1, flags, func, ptr);
-               result += func(ptr, "\"", 1);
-               result += escape(fjson_object_iter_peek_name(&it), func, ptr);
-               if (flags & FJSON_TO_STRING_SPACED) result += func(ptr, "\": ", 
3);
-               else result += func(ptr, "\":", 2);
-               result += write(fjson_object_iter_peek_value(&it), level+1, 
flags, func, ptr);
+               if (flags & FJSON_TO_STRING_SPACED) result += 
buffer_append(buffer, " ", 1);
+               result += indent(level+1, flags, buffer);
+               result += buffer_append(buffer, "\"", 1);
+               result += escape(fjson_object_iter_peek_name(&it), buffer);
+               if (flags & FJSON_TO_STRING_SPACED) result += 
buffer_append(buffer, "\": ", 3);
+               else result += buffer_append(buffer, "\":", 2);
+               result += write(fjson_object_iter_peek_value(&it), level+1, 
flags, buffer);
                fjson_object_iter_next(&it);
        }
        if (flags & FJSON_TO_STRING_PRETTY)
        {
-               if (had_children) result += func(ptr, "\n", 1);
-               result += indent(level, flags, func, ptr);
+               if (had_children) result += buffer_append(buffer, "\n", 1);
+               result += indent(level, flags, buffer);
        }
-       if (flags & FJSON_TO_STRING_SPACED) result += func(ptr, /*{*/ " }", 2);
-       else result += func(ptr, /*{*/ "}", 1);
+       if (flags & FJSON_TO_STRING_SPACED) result += buffer_append(buffer, 
/*{*/ " }", 2);
+       else result += buffer_append(buffer, /*{*/ "}", 1);
        return result;
 }
 
 /* write a json boolean */
 
-static size_t write_boolean(struct fjson_object* jso, fjson_write_fn *func, 
void *ptr)
+static size_t write_boolean(struct fjson_object* jso, struct buffer *buffer)
 {
-       if (jso->o.c_boolean) return func(ptr, "true", 4);
-       else return func(ptr, "false", 5);
+       if (jso->o.c_boolean) return buffer_append(buffer, "true", 4);
+       else return buffer_append(buffer, "false", 5);
 }
 
 /* write a json int */
 
-static size_t write_int(struct fjson_object* jso, fjson_write_fn *func, void 
*ptr)
+static size_t write_int(struct fjson_object* jso, struct buffer *buffer)
 {
-       // temporary buffer
-       char tempbuffer[32];
-       size_t bytes = snprintf(tempbuffer, sizeof(tempbuffer), "%" PRId64, 
jso->o.c_int64);
-       return func(ptr, tempbuffer, bytes);
+       // printf into the buffer
+       return buffer_printf(buffer, "%" PRId64, jso->o.c_int64);
 }
 
 /* write a json floating point */
 
-static size_t write_double(struct fjson_object* jso, int flags, fjson_write_fn 
*func, void *ptr)
+static size_t write_double(struct fjson_object* jso, int flags, struct buffer 
*buffer)
 {
-       char buf[128], *p, *q;
-       int size;
+       // return value for the function
+       size_t result = 0;
+
+       // helper functions to fix the output
+       char *buf, *p, *q;
+
+       // needed for modf()
+       double dummy;
+
+       // if the original value is set, we reuse that
+       if (jso->o.c_double.source) return buffer_append(buffer, 
jso->o.c_double.source, strlen(jso->o.c_double.source));
+
        /* Although JSON RFC does not support
         * NaN or Infinity as numeric values
         * ECMA 262 section 9.8.1 defines
         * how to handle these cases as strings
         */
-       if(isnan(jso->o.c_double))
-               size = snprintf(buf, sizeof(buf), "NaN");
-       else if(isinf(jso->o.c_double))
-               if(jso->o.c_double > 0)
-                       size = snprintf(buf, sizeof(buf), "Infinity");
-               else
-                       size = snprintf(buf, sizeof(buf), "-Infinity");
-       else
-               size = snprintf(buf, sizeof(buf), "%.17g", jso->o.c_double);
+       if(isnan(jso->o.c_double.value)) return buffer_append(buffer, "NaN", 3);
+       if(isinf(jso->o.c_double.value)) return buffer_printf(buffer, 
jso->o.c_double.value > 0 ? "Infinity" : "-Infinity");
+
+       // store the beginning of the buffer (this is where buffer_printf() 
will most likely write)
+       buf = buffer->buffer + buffer->filled;
 
+       // write to the buffer
+       result = buffer_printf(buffer, (modf(jso->o.c_double.value, 
&dummy)==0)?"%.17g.0":"%.17g", jso->o.c_double.value);
+
+       // if the buffer got flushed
+       if (buffer->buffer + buffer->filled < buf) buf = buffer->buffer;
+
+       // if localization stuff caused "," to be generated instead of "."
+       // @todo is there not a nicer way to work around that???
        p = strchr(buf, ',');
        if (p) {
                *p = '.';
        } else {
                p = strchr(buf, '.');
        }
+
+       // remove trailing zero's
        if (p && (flags & FJSON_TO_STRING_NOZERO)) {
                /* last useful digit, always keep 1 zero */
                p++;
@@ -228,67 +420,68 @@
                        if (*q!='0') p=q;
                }
                /* drop trailing zeroes */
-               *(++p) = 0;
-               size = p-buf;
+               buffer->filled = p - buffer->buffer;
        }
-       return func(ptr, buf, size);
+
+       // done
+       return result;
 }
 
 /* write a json string */
 
-static size_t write_string(struct fjson_object* jso, fjson_write_fn *func, 
void *ptr)
+static size_t write_string(struct fjson_object* jso, struct buffer *buffer)
 {
-       return func(ptr, "\"", 1) + escape(get_string_component(jso), func, 
ptr) + func(ptr, "\"", 1);
+       return buffer_append(buffer, "\"", 1) + 
escape(get_string_component(jso), buffer) + buffer_append(buffer, "\"", 1);
 }
 
 /* write a json array */
 
-static size_t write_array(struct fjson_object* jso, int level, int flags, 
fjson_write_fn *func, void *ptr)
+static size_t write_array(struct fjson_object* jso, int level, int flags, 
struct buffer *buffer)
 {
        int had_children = 0;
        int ii;
        size_t result = 0;
-       result += func(ptr, "[", 1);
-       if (flags & FJSON_TO_STRING_PRETTY) result += func(ptr, "\n", 1);
+       result += buffer_append(buffer, "[", 1);
+       if (flags & FJSON_TO_STRING_PRETTY) result += buffer_append(buffer, 
"\n", 1);
        for(ii=0; ii < fjson_object_array_length(jso); ii++)
        {
                if (had_children)
                {
-                       result += func(ptr, ",", 1);
-                       if (flags & FJSON_TO_STRING_PRETTY) result += func(ptr, 
"\n", 1);
+                       result += buffer_append(buffer, ",", 1);
+                       if (flags & FJSON_TO_STRING_PRETTY) result += 
buffer_append(buffer, "\n", 1);
                }
                had_children = 1;
-               if (flags & FJSON_TO_STRING_SPACED) result += func(ptr, " ", 1);
-               result += indent(level + 1, flags, func, ptr);
-               result += write(fjson_object_array_get_idx(jso, ii), level+1, 
flags, func, ptr);
+               if (flags & FJSON_TO_STRING_SPACED) result += 
buffer_append(buffer, " ", 1);
+               result += indent(level + 1, flags, buffer);
+               result += write(fjson_object_array_get_idx(jso, ii), level+1, 
flags, buffer);
        }
        if (flags & FJSON_TO_STRING_PRETTY)
        {
-               if (had_children) result += func(ptr, "\n", 1);
-               result += indent(level, flags, func, ptr);
+               if (had_children) result += buffer_append(buffer, "\n", 1);
+               result += indent(level, flags, buffer);
        }
 
-       if (flags & FJSON_TO_STRING_SPACED) result += func(ptr, " ]", 2);
-       else result += func(ptr, "]", 1);
+       if (flags & FJSON_TO_STRING_SPACED) result += buffer_append(buffer, " 
]", 2);
+       else result += buffer_append(buffer, "]", 1);
        return result;
 }
 
 /* write a json value */
 
-static size_t write(struct fjson_object *jso, int level, int flags, 
fjson_write_fn *func, void *ptr)
+static size_t write(struct fjson_object *jso, int level, int flags, struct 
buffer *buffer)
 {
        // if object is not set
-       if (!jso) return func(ptr, "null", 4);
+       if (!jso) return buffer_append(buffer, "null", 4);
 
        // check type
        switch(jso->o_type) {
-       case fjson_type_null:       return func(ptr, "null", 4);
-       case fjson_type_boolean:    return write_boolean(jso, func, ptr);
-       case fjson_type_double:     return write_double(jso, flags, func, ptr);
-       case fjson_type_int:        return write_int(jso, func, ptr);
-       case fjson_type_object:     return write_object(jso, level, flags, 
func, ptr);
-       case fjson_type_array:      return write_array(jso, level, flags, func, 
ptr);
-       case fjson_type_string:     return write_string(jso, func, ptr);
+       case fjson_type_null:       return buffer_append(buffer, "null", 4);
+       case fjson_type_boolean:    return write_boolean(jso, buffer);
+       case fjson_type_double:     return write_double(jso, flags, buffer);
+       case fjson_type_int:        return write_int(jso, buffer);
+       case fjson_type_object:     return write_object(jso, level, flags, 
buffer);
+       case fjson_type_array:      return write_array(jso, level, flags, 
buffer);
+       case fjson_type_string:     return write_string(jso, buffer);
        default:                    return 0;
        }
 }
@@ -300,12 +493,47 @@
        return fwrite(buffer, 1, size, ptr);
 }
 
+/* dummy output function that does not output, but is used to calculate the 
size */
+
+static size_t calculate(void __attribute__((unused)) *ptr, const char 
__attribute__((unused)) *buffer, size_t size)
+{
+       return size;
+}
+
+/* extended dump to which the helper buffer can be passed */
+
+size_t fjson_object_dump_buffered(struct fjson_object *jso, int flags, char 
*temp,
+size_t size, fjson_write_fn *func, void *ptr)
+{
+       // construct a buffer
+       struct buffer object;
+
+       // initialize the properties
+       object.buffer = temp;
+       object.size = size;
+       object.filled = 0;
+       object.overflow = func;
+       object.ptr = ptr;
+
+       // write the value
+       size_t result = write(jso, 0, flags, &object);
+
+       // ready if buffer is now empty
+       if (object.size == 0) return result;
+
+       // flush the buffer
+       return result + buffer_flush(&object);
+}
+
 /* extended dump function to string */
 
 size_t fjson_object_dump_ext(struct fjson_object *jso, int flags, 
fjson_write_fn *func, void *ptr)
 {
-       // write the value
-       return write(jso, 0, flags, func, ptr);
+       // create a local 1k buffer on the stack
+       char buffer[1024];
+
+       // pass on to the other function
+       return fjson_object_dump_buffered(jso, flags, buffer, 1024, func, ptr);
 }
 
 /* more simple write function */
@@ -313,7 +541,25 @@
 size_t fjson_object_dump(struct fjson_object *jso, fjson_write_fn *func, void 
*ptr)
 {
        // write the value
-       return write(jso, 0, FJSON_TO_STRING_SPACED, func, ptr);
+       return fjson_object_dump_ext(jso, FJSON_TO_STRING_SPACED, func, ptr);
+}
+
+/* extended function to calculate the size */
+
+size_t fjson_object_size_ext(struct fjson_object *jso, int flags)
+{
+       // write the value with a dummy function (this is a simple 
implementation that
+       // can later be optimized in a pure size-calculating function)
+       return fjson_object_dump_ext(jso, flags, &calculate, NULL);
+}
+
+/* function to calculate the size */
+
+size_t fjson_object_size(struct fjson_object *jso)
+{
+       // write the value with a dummy function (this is a simple 
implementation that
+       // can later be optimized in a pure size-calculating function)
+       return fjson_object_dump(jso, &calculate, NULL);
 }
 
 /* write to a file* */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/tests/Makefile.am 
new/libfastjson-0.99.7/tests/Makefile.am
--- old/libfastjson-0.99.6/tests/Makefile.am    2017-05-11 14:02:02.000000000 
+0200
+++ new/libfastjson-0.99.7/tests/Makefile.am    2017-10-16 11:33:40.000000000 
+0200
@@ -17,7 +17,6 @@
 TESTS+= test_locale.test
 TESTS+= test_charcase.test
 TESTS+= test_printbuf.test
-TESTS+= test_set_serializer.test
 TESTS+= test_obj_iter-del.test
 TESTS+= test_object_object_add_ex.test
 TESTS+= test_many_subobj.test
@@ -43,7 +42,6 @@
 chk_version_SOURCES = chk_version.c
 
 test_printbuf_SOURCES = test_printbuf.c
-test_set_serializer_SOURCES = test_set_serializer.c
 
 # Note: handled by test1.test
 check_PROGRAMS += test1Formatted 
@@ -82,7 +80,6 @@
 EXTRA_DIST += test_parse_int64.expected
 EXTRA_DIST += test_printbuf.expected
 EXTRA_DIST += testReplaceExisting.expected
-EXTRA_DIST += test_set_serializer.expected
 EXTRA_DIST += test_obj_iter-del.expected
 EXTRA_DIST += test_object_object_add_ex.expected
 EXTRA_DIST += test_object_object_add_exFormatted_plain.expected
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/tests/Makefile.in 
new/libfastjson-0.99.7/tests/Makefile.in
--- old/libfastjson-0.99.6/tests/Makefile.in    2017-05-11 16:11:06.000000000 
+0200
+++ new/libfastjson-0.99.7/tests/Makefile.in    2017-10-16 11:43:17.000000000 
+0200
@@ -90,10 +90,9 @@
 TESTS = ucs_copyright_char.test test_float.test test1.test test2.test \
        test4.test testReplaceExisting.test test_parse_int64.test \
        test_cast.test test_parse.test test_locale.test \
-       test_charcase.test test_printbuf.test test_set_serializer.test \
-       test_obj_iter-del.test test_object_object_add_ex.test \
-       test_many_subobj.test test_obj_obj_get_ex-null.test \
-       chk_version$(EXEEXT)
+       test_charcase.test test_printbuf.test test_obj_iter-del.test \
+       test_object_object_add_ex.test test_many_subobj.test \
+       test_obj_obj_get_ex-null.test chk_version$(EXEEXT)
 check_PROGRAMS = $(am__EXEEXT_1) chk_version$(EXEEXT) \
        cr_obj_multi$(EXEEXT) chk_version$(EXEEXT) \
        cr_obj_multi$(EXEEXT) test1Formatted$(EXEEXT) \
@@ -122,9 +121,9 @@
        testReplaceExisting$(EXEEXT) test_parse_int64$(EXEEXT) \
        test_cast$(EXEEXT) test_parse$(EXEEXT) test_locale$(EXEEXT) \
        test_charcase$(EXEEXT) test_printbuf$(EXEEXT) \
-       test_set_serializer$(EXEEXT) test_obj_iter-del$(EXEEXT) \
-       test_object_object_add_ex$(EXEEXT) test_many_subobj$(EXEEXT) \
-       test_obj_obj_get_ex-null$(EXEEXT) chk_version$(EXEEXT)
+       test_obj_iter-del$(EXEEXT) test_object_object_add_ex$(EXEEXT) \
+       test_many_subobj$(EXEEXT) test_obj_obj_get_ex-null$(EXEEXT) \
+       chk_version$(EXEEXT)
 am_chk_version_OBJECTS = chk_version.$(OBJEXT)
 chk_version_OBJECTS = $(am_chk_version_OBJECTS)
 chk_version_LDADD = $(LDADD)
@@ -237,11 +236,6 @@
 test_printbuf_LDADD = $(LDADD)
 test_printbuf_DEPENDENCIES = $(top_builddir)/libfastjson.la \
        $(top_builddir)/libfastjson-internal.la
-am_test_set_serializer_OBJECTS = test_set_serializer.$(OBJEXT)
-test_set_serializer_OBJECTS = $(am_test_set_serializer_OBJECTS)
-test_set_serializer_LDADD = $(LDADD)
-test_set_serializer_DEPENDENCIES = $(top_builddir)/libfastjson.la \
-       $(top_builddir)/libfastjson-internal.la
 ucs_copyright_char_SOURCES = ucs_copyright_char.c
 ucs_copyright_char_OBJECTS = ucs_copyright_char.$(OBJEXT)
 ucs_copyright_char_LDADD = $(LDADD)
@@ -289,7 +283,7 @@
        test_object_object_add_ex.c \
        $(test_object_object_add_exFormatted_SOURCES) test_parse.c \
        test_parse_int64.c $(test_printbuf_SOURCES) \
-       $(test_set_serializer_SOURCES) ucs_copyright_char.c
+       ucs_copyright_char.c
 DIST_SOURCES = $(chk_version_SOURCES) $(cr_obj_multi_SOURCES) test1.c \
        $(test1Formatted_SOURCES) test2.c $(test2Formatted_SOURCES) \
        test4.c testReplaceExisting.c test_cast.c test_charcase.c \
@@ -298,7 +292,7 @@
        test_object_object_add_ex.c \
        $(test_object_object_add_exFormatted_SOURCES) test_parse.c \
        test_parse_int64.c $(test_printbuf_SOURCES) \
-       $(test_set_serializer_SOURCES) ucs_copyright_char.c
+       ucs_copyright_char.c
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -658,7 +652,6 @@
 cr_obj_multi_SOURCES = cr_obj_multi.c
 chk_version_SOURCES = chk_version.c
 test_printbuf_SOURCES = test_printbuf.c
-test_set_serializer_SOURCES = test_set_serializer.c
 test1Formatted_SOURCES = test1.c parse_flags.c parse_flags.h
 test1Formatted_CPPFLAGS = -DTEST_FORMATTED
 test2Formatted_SOURCES = test2.c parse_flags.c parse_flags.h
@@ -674,8 +667,8 @@
        test_cast.expected test_charcase.expected test_locale.expected \
        test_null.expected test_parse.expected \
        test_parse_int64.expected test_printbuf.expected \
-       testReplaceExisting.expected test_set_serializer.expected \
-       test_obj_iter-del.expected test_object_object_add_ex.expected \
+       testReplaceExisting.expected test_obj_iter-del.expected \
+       test_object_object_add_ex.expected \
        test_object_object_add_exFormatted_plain.expected \
        test_object_object_add_exFormatted_pretty.expected \
        test_object_object_add_exFormatted_spaced.expected \
@@ -805,10 +798,6 @@
        @rm -f test_printbuf$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_printbuf_OBJECTS) $(test_printbuf_LDADD) 
$(LIBS)
 
-test_set_serializer$(EXEEXT): $(test_set_serializer_OBJECTS) 
$(test_set_serializer_DEPENDENCIES) $(EXTRA_test_set_serializer_DEPENDENCIES) 
-       @rm -f test_set_serializer$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(test_set_serializer_OBJECTS) 
$(test_set_serializer_LDADD) $(LIBS)
-
 ucs_copyright_char$(EXEEXT): $(ucs_copyright_char_OBJECTS) 
$(ucs_copyright_char_DEPENDENCIES) $(EXTRA_ucs_copyright_char_DEPENDENCIES) 
        @rm -f ucs_copyright_char$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(ucs_copyright_char_OBJECTS) 
$(ucs_copyright_char_LDADD) $(LIBS)
@@ -842,7 +831,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_parse.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_parse_int64.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_printbuf.Po@am__quote@
-@AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/test_set_serializer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/ucs_copyright_char.Po@am__quote@
 
 .c.o:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/tests/test_set_serializer.c 
new/libfastjson-0.99.7/tests/test_set_serializer.c
--- old/libfastjson-0.99.6/tests/test_set_serializer.c  2017-05-11 
14:02:02.000000000 +0200
+++ new/libfastjson-0.99.7/tests/test_set_serializer.c  1970-01-01 
01:00:00.000000000 +0100
@@ -1,81 +0,0 @@
-#include "config.h"
-#include <stdio.h>
-#include <string.h>
-
-#include "../json.h"
-#include "../printbuf.h"
-#include "../debug.h"
-
-/* this is a work-around until we manage to fix configure.ac */
-#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
-
-#define CHK(x) if (!(x)) { \
-       printf("%s:%d: unexpected result with '%s'\n", \
-               __FILE__, __LINE__, #x); \
-       exit(1); \
-}
-
-struct myinfo {
-       int value;
-};
-
-static int freeit_was_called = 0;
-static void freeit(fjson_object __attribute__((unused)) *jso, void *userdata)
-{
-       struct myinfo *info = userdata;
-       printf("freeit, value=%d\n", info->value);
-       // Don't actually free anything here, the userdata is stack allocated.
-       freeit_was_called = 1;
-}
-static int custom_serializer(struct fjson_object __attribute__((unused)) *o,
-                                       struct printbuf *pb,
-                                       int __attribute__((unused)) level,
-                                       int __attribute__((unused)) flags)
-{
-       sprintbuf(pb, "Custom Output");
-       return 0;
-}
-
-int main(int __attribute__((unused)) argc, char __attribute__((unused)) **argv)
-{
-       fjson_object *my_object;
-
-       MC_SET_DEBUG(1);
-
-       printf("Test setting, then resetting a custom serializer:\n");
-       my_object = fjson_object_new_object();
-       fjson_object_object_add(my_object, "abc", fjson_object_new_int(12));
-       fjson_object_object_add(my_object, "foo", 
fjson_object_new_string("bar"));
-
-       printf("my_object.to_string(standard)=%s\n", 
fjson_object_to_json_string(my_object));
-
-       struct myinfo userdata = { .value = 123 };
-       fjson_object_set_serializer(my_object, custom_serializer, &userdata, 
freeit);
-
-       printf("my_object.to_string(custom serializer)=%s\n", 
fjson_object_to_json_string(my_object));
-
-       printf("Next line of output should be from the custom freeit 
function:\n");
-       freeit_was_called = 0;
-       fjson_object_set_serializer(my_object, NULL, NULL, NULL);
-       CHK(freeit_was_called);
-
-       printf("my_object.to_string(standard)=%s\n", 
fjson_object_to_json_string(my_object));
-
-       fjson_object_put(my_object);
-
-       // ============================================
-
-       my_object = fjson_object_new_object();
-       printf("Check that the custom serializer isn't free'd until the last 
fjson_object_put:\n");
-       fjson_object_set_serializer(my_object, custom_serializer, &userdata, 
freeit);
-       fjson_object_get(my_object);
-       fjson_object_put(my_object);
-       printf("my_object.to_string(custom serializer)=%s\n", 
fjson_object_to_json_string(my_object));
-       printf("Next line of output should be from the custom freeit 
function:\n");
-
-       freeit_was_called = 0;
-       fjson_object_put(my_object);
-       CHK(freeit_was_called);
-
-       return 0;
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libfastjson-0.99.6/tests/test_set_serializer.expected 
new/libfastjson-0.99.7/tests/test_set_serializer.expected
--- old/libfastjson-0.99.6/tests/test_set_serializer.expected   2017-05-11 
14:02:02.000000000 +0200
+++ new/libfastjson-0.99.7/tests/test_set_serializer.expected   1970-01-01 
01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-Test setting, then resetting a custom serializer:
-my_object.to_string(standard)={ "abc": 12, "foo": "bar" }
-my_object.to_string(custom serializer)=Custom Output
-Next line of output should be from the custom freeit function:
-freeit, value=123
-my_object.to_string(standard)={ "abc": 12, "foo": "bar" }
-Check that the custom serializer isn't free'd until the last fjson_object_put:
-my_object.to_string(custom serializer)=Custom Output
-Next line of output should be from the custom freeit function:
-freeit, value=123
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfastjson-0.99.6/tests/test_set_serializer.test 
new/libfastjson-0.99.7/tests/test_set_serializer.test
--- old/libfastjson-0.99.6/tests/test_set_serializer.test       2017-05-11 
14:02:02.000000000 +0200
+++ new/libfastjson-0.99.7/tests/test_set_serializer.test       1970-01-01 
01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-#!/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_set_serializer
-exit $?


Reply via email to