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 - astieger@suse.com
+
+- 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.h...
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.h...
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 .
#
@@ -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='rsyslog@lists.adiscon.com'
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], [rsyslog@lists.adiscon.com])
+AC_INIT([libfastjson], [0.99.7], [rsyslog@lists.adiscon.com])
# 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
* 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
#include
+#ifdef HAVE_STDARG_H
+# include
+#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
-#include
-
-#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 $?