diff options
author | Eric Haszlakiewicz <erh+git@nimenees.com> | 2013-02-26 21:09:10 -0600 |
---|---|---|
committer | Eric Haszlakiewicz <erh+git@nimenees.com> | 2013-02-26 21:09:10 -0600 |
commit | 5b36a432c8b13f3534ade4c4b5ac721b6e35287a (patch) | |
tree | 624962b6a45b3c9bfa642c773aabe5fdab8a59e3 | |
parent | 9b64c05ff9feb1cdb1e5ae5e134e5e6ff85dbb1b (diff) | |
parent | 32d149c8f60a5bdad4f678013a83d052ffd8ad43 (diff) | |
download | json-c-5b36a432c8b13f3534ade4c4b5ac721b6e35287a.tar.gz |
Merge branch 'remicollet-issue-float'
Conflicts:
json_util.c
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | json_object.c | 23 | ||||
-rw-r--r-- | json_object.h | 4 | ||||
-rw-r--r-- | json_tokener.c | 18 | ||||
-rw-r--r-- | json_util.c | 5 | ||||
-rw-r--r-- | json_util.h | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/test_locale.c | 31 |
8 files changed, 85 insertions, 4 deletions
diff --git a/configure.in b/configure.in index 5a3c0df..1a428b6 100644 --- a/configure.in +++ b/configure.in @@ -23,7 +23,7 @@ AM_CONDITIONAL(ENABLE_OLDNAME_COMPAT, [test "x${enable_oldname_compat}" != "xno" AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(json_config.h) AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/cdefs.h] [sys/param.h] stdarg.h) +AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/cdefs.h] [sys/param.h] stdarg.h locale.h) AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public define for json_inttypes.h])]) # Checks for typedefs, structures, and compiler characteristics. @@ -35,7 +35,7 @@ AC_FUNC_VPRINTF AC_FUNC_MEMCMP AC_FUNC_MALLOC AC_FUNC_REALLOC -AC_CHECK_FUNCS(strcasecmp strdup strndup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp) +AC_CHECK_FUNCS(strcasecmp strdup strndup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale) #check if .section.gnu.warning accepts long strings (for __warn_references) AC_LANG_PUSH([C]) diff --git a/json_object.c b/json_object.c index 9dc6637..f2b5ce0 100644 --- a/json_object.c +++ b/json_object.c @@ -559,7 +559,28 @@ static int json_object_double_to_json_string(struct json_object* jso, int level, int flags) { - return sprintbuf(pb, "%f", jso->o.c_double); + char buf[128], *p, *q; + int size; + + size = snprintf(buf, 128, "%f", jso->o.c_double); + p = strchr(buf, ','); + if (p) { + *p = '.'; + } else { + p = strchr(buf, '.'); + } + if (p && (flags & JSON_C_TO_STRING_NOZERO)) { + /* last useful digit, always keep 1 zero */ + p++; + for (q=p ; *q ; q++) { + if (*q!='0') p=q; + } + /* drop trailing zeroes */ + *(++p) = 0; + size = p-buf; + } + printbuf_memappend(pb, buf, size); + return size; } struct json_object* json_object_new_double(double d) diff --git a/json_object.h b/json_object.h index e18af8a..7085d0a 100644 --- a/json_object.h +++ b/json_object.h @@ -42,6 +42,10 @@ extern "C" { * for an example of the format. */ #define JSON_C_TO_STRING_PRETTY (1<<1) +/** + * A flag to drop trailing zero for float values + */ +#define JSON_C_TO_STRING_NOZERO (1<<2) #undef FALSE #define FALSE ((json_bool)0) diff --git a/json_tokener.c b/json_tokener.c index e0edca0..8040fea 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -31,6 +31,10 @@ #include "json_tokener.h" #include "json_util.h" +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif /* HAVE_LOCALE_H */ + #if !HAVE_STRDUP && defined(_MSC_VER) /* MSC has the version as _strdup */ # define strdup _strdup @@ -239,6 +243,13 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, { struct json_object *obj = NULL; char c = '\1'; +#ifdef HAVE_SETLOCALE + char *oldlocale=NULL, *tmplocale; + + tmplocale = setlocale(LC_NUMERIC, NULL); + if (tmplocale) oldlocale = strdup(tmplocale); + setlocale(LC_NUMERIC, "C"); +#endif tok->char_offset = 0; tok->err = json_tokener_success; @@ -597,7 +608,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, double numd; if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { current = json_object_new_int64(num64); - } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) { + } else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) { current = json_object_new_double(numd); } else { tok->err = json_tokener_error_parse_number; @@ -736,6 +747,11 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, tok->err = json_tokener_error_parse_eof; } +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, oldlocale); + if (oldlocale) free(oldlocale); +#endif + if (tok->err == json_tokener_success) { json_object *ret = json_object_get(current); diff --git a/json_util.c b/json_util.c index 194f290..111fa01 100644 --- a/json_util.c +++ b/json_util.c @@ -146,6 +146,11 @@ int json_object_to_file(char *filename, struct json_object *obj) return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN); } +int json_parse_double(const char *buf, double *retval) +{ + return (sscanf(buf, "%lf", retval)==1 ? 0 : 1); +} + /* * Not all implementations of sscanf actually work properly. * Check whether the one we're currently using does, and if diff --git a/json_util.h b/json_util.h index 277c3a7..b9a69c8 100644 --- a/json_util.h +++ b/json_util.h @@ -25,6 +25,7 @@ extern struct json_object* json_object_from_file(const char *filename); extern int json_object_to_file(char *filename, struct json_object *obj); extern int json_object_to_file_ext(char *filename, struct json_object *obj, int flags); extern int json_parse_int64(const char *buf, int64_t *retval); +extern int json_parse_double(const char *buf, double *retval); /** diff --git a/tests/Makefile.am b/tests/Makefile.am index 0f06590..881c7e7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,6 +11,7 @@ check_PROGRAMS += test_parse_int64 check_PROGRAMS += test_null check_PROGRAMS += test_cast check_PROGRAMS += test_parse +check_PROGRAMS += test_locale test1_LDADD = $(LIBJSON_LA) @@ -36,6 +37,8 @@ test_cast_LDADD = $(LIBJSON_LA) test_parse_LDADD = $(LIBJSON_LA) +test_locale_LDADD = $(LIBJSON_LA) + TESTS = test1.test test2.test test4.test testReplaceExisting.test parse_int64.test test_null.test test_cast.test test_parse.test TESTS+= test_printbuf.test diff --git a/tests/test_locale.c b/tests/test_locale.c new file mode 100644 index 0000000..da070cf --- /dev/null +++ b/tests/test_locale.c @@ -0,0 +1,31 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <assert.h> + +#include "config.h" +#include "json.h" +#include "json_tokener.h" + +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif /* HAVE_LOCALE_H */ + +int main(int argc, char **argv) +{ + json_object *new_obj; +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, "de_DE"); +#else + printf("No locale\n"); +#endif + + MC_SET_DEBUG(1); + + new_obj = json_tokener_parse("[1.2,3.4,123456.78,5.0,2.3e10]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + printf("new_obj.to_string()=%s\n", json_object_to_json_string_ext(new_obj,JSON_C_TO_STRING_NOZERO)); + json_object_put(new_obj); +} + |