aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2011-10-07 23:55:49 +1030
committerMark Pulford <mark@kyne.com.au>2011-10-07 23:55:49 +1030
commit049691cb11115fbdb750021556cad3507fad4e69 (patch)
tree3ef83227a086c2dbd70633a55a8425335a8e92fb
parent48c5cf183fa7cab608168fdec2406a1ca3cb2c11 (diff)
downloadlua-cjson-049691cb11115fbdb750021556cad3507fad4e69.tar.gz
lua-cjson-049691cb11115fbdb750021556cad3507fad4e69.tar.bz2
lua-cjson-049691cb11115fbdb750021556cad3507fad4e69.zip
Add USE_POSIX_SETLOCALE option
Add USE_POSIX_SETLOCALE option for platforms missing uselocale(). Document locale options in README, Makefile & rockspec. Also: - Rename USE_POSIX_LOCALE define to USE_POSIX_USELOCALE. - Use uselocale() by default through Makefile (Linux, OSX). - Use setlocale() by default through rockspec (other platforms).
-rw-r--r--Makefile8
-rw-r--r--README12
-rw-r--r--TODO2
-rw-r--r--lua-cjson-1.0.3-1.rockspec5
-rw-r--r--lua_cjson.c38
5 files changed, 52 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 5857aee..082c720 100644
--- a/Makefile
+++ b/Makefile
@@ -23,8 +23,12 @@ override CFLAGS += -fpic -I$(LUA_INCLUDE_DIR) -DVERSION=\"$(CJSON_VERSION)\"
23# Handle Solaris platforms that are missing isinf(). 23# Handle Solaris platforms that are missing isinf().
24#override CFLAGS += -DUSE_INTERNAL_ISINF 24#override CFLAGS += -DUSE_INTERNAL_ISINF
25# Handle locales that use comma as a decimal separator on locale aware 25# Handle locales that use comma as a decimal separator on locale aware
26# platforms. Requires POSIX-1.2008 support. 26# platforms (optional, but recommended).
27override CFLAGS += -DUSE_POSIX_LOCALE 27# USE_POSIX_USELOCALE: Linux, OSX. Thread safe. Recommended option.
28# USE_POSIX_SETLOCALE: Works on all ANSI C platforms. May be used when
29# thread-safety isn't required.
30override CFLAGS += -DUSE_POSIX_USELOCALE
31#override CFLAGS += -DUSE_POSIX_SETLOCALE
28 32
29INSTALL ?= install 33INSTALL ?= install
30 34
diff --git a/README b/README
index e8c3abe..f863d73 100644
--- a/README
+++ b/README
@@ -309,6 +309,18 @@ Lua CJSON will generate an error if asked to serialise Lua functions,
309userdata, lightuserdata or threads. 309userdata, lightuserdata or threads.
310 310
311 311
312Locale handling
313---------------
314
315Lua CJSON uses strtod() and snprintf() to perform numeric conversion
316as they are usually well supported, fast and bug free.
317
318To ensure JSON encoding/decoding works correctly for locales using
319comma decimal separators, Lua CJSON must be compiled with either
320USE_POSIX_USELOCALE or USE_POSIX_SETLOCALE. See the Makefile or the
321rockspec for details.
322
323
312References 324References
313========== 325==========
314 326
diff --git a/TODO b/TODO
index 9dbde9c..1345448 100644
--- a/TODO
+++ b/TODO
@@ -2,5 +2,3 @@
2 - Optionally create an object for settings. Clone function. 2 - Optionally create an object for settings. Clone function.
3 3
4- Convert documentation into structured source format 4- Convert documentation into structured source format
5
6- Add setlocale() support for non-POSIX 2008 operating systems
diff --git a/lua-cjson-1.0.3-1.rockspec b/lua-cjson-1.0.3-1.rockspec
index 3f8e981..28514e1 100644
--- a/lua-cjson-1.0.3-1.rockspec
+++ b/lua-cjson-1.0.3-1.rockspec
@@ -25,9 +25,12 @@ build = {
25 cjson = { 25 cjson = {
26 sources = { "lua_cjson.c", "strbuf.c" }, 26 sources = { "lua_cjson.c", "strbuf.c" },
27-- Optional workarounds: 27-- Optional workarounds:
28-- USE_POSIX_USELOCALE: Linux, OSX. Thread safe. Recommended.
29-- USE_POSIX_SETLOCALE: Works on all ANSI C platforms. May be used when
30-- thread-safety isn't required.
28-- USE_INTERNAL_ISINF: Provide internal isinf() implementation. Required 31-- USE_INTERNAL_ISINF: Provide internal isinf() implementation. Required
29-- on some Solaris platforms. 32-- on some Solaris platforms.
30 defines = { "VERSION=\"1.0.3\"" } 33 defines = { "VERSION=\"1.0.3\"", "USE_POSIX_SETLOCALE" }
31 } 34 }
32 }, 35 },
33 copy_directories = { "tests" } 36 copy_directories = { "tests" }
diff --git a/lua_cjson.c b/lua_cjson.c
index ad3818d..8efd127 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -44,26 +44,46 @@
44 44
45#include "strbuf.h" 45#include "strbuf.h"
46 46
47#ifdef USE_POSIX_LOCALE 47/* Support to reset locale to POSIX for strtod() / sprintf().
48/* Reset locale to POSIX for strtod() / sprintf().
49 * Some locales use comma as a decimal separator. This breaks JSON. */ 48 * Some locales use comma as a decimal separator. This breaks JSON. */
49#ifdef USE_POSIX_USELOCALE
50
51#ifdef USE_POSIX_SETLOCALE
52#error Must not define USE_POSIX_USELOCALE and USE_POSIX_SETLOCALE simultaneously.
53#endif
50 54
51/* unistd.h defines _POSIX_VERSION */ 55/* unistd.h defines _POSIX_VERSION */
52#include <unistd.h> 56#include <unistd.h>
57
53#if _POSIX_VERSION >= 200809L 58#if _POSIX_VERSION >= 200809L
54/* POSIX.1-2008 adds threadsafe locale support */ 59/* POSIX.1-2008 adds threadsafe locale support */
55#include <locale.h> 60#include <locale.h>
56#elif defined(_POSIX_VERSION) 61#elif defined(_POSIX_VERSION)
57/* Some pre-POSIX.1-2008 operating systems use xlocale.h instead */ 62/* Some pre-POSIX.1-2008 operating systems offer xlocale.h instead */
58#include <xlocale.h> 63#include <xlocale.h>
59#else 64#else
60#error Missing _POSIX_VERSION define 65#error Missing _POSIX_VERSION define
61#endif 66#endif /* _POSIX_VERSION */
67
62#define LOCALE_SET_POSIX(x) (x)->saved_locale = uselocale((x)->posix_locale) 68#define LOCALE_SET_POSIX(x) (x)->saved_locale = uselocale((x)->posix_locale)
63#define LOCALE_RESTORE(x) uselocale((x)->saved_locale) 69#define LOCALE_RESTORE(x) uselocale((x)->saved_locale)
64#else 70
71#elif defined(USE_POSIX_SETLOCALE)
72/* ANSI C / ISO C90 implementation. Not thread-safe, affects entire process. */
73#include <locale.h>
74
75#define LOCALE_SET_POSIX(x) \
76 do { \
77 (x)->saved_locale = setlocale(LC_NUMERIC, NULL); \
78 setlocale(LC_NUMERIC, "C"); \
79 } while(0)
80#define LOCALE_RESTORE(x) setlocale(LC_NUMERIC, (x)->saved_locale)
81
82#else /* Do not work around locale support in strtod() / sprintf() */
83
65#define LOCALE_SET_POSIX(x) do { } while(0) 84#define LOCALE_SET_POSIX(x) do { } while(0)
66#define LOCALE_RESTORE(x) do { } while(0) 85#define LOCALE_RESTORE(x) do { } while(0)
86
67#endif 87#endif
68 88
69/* Some Solaris platforms are missing isinf(). */ 89/* Some Solaris platforms are missing isinf(). */
@@ -122,9 +142,11 @@ typedef struct {
122 char *char2escape[256]; /* Encoding */ 142 char *char2escape[256]; /* Encoding */
123#endif 143#endif
124 strbuf_t encode_buf; 144 strbuf_t encode_buf;
125#if USE_POSIX_LOCALE 145#if defined(USE_POSIX_USELOCALE)
126 locale_t saved_locale; 146 locale_t saved_locale;
127 locale_t posix_locale; 147 locale_t posix_locale;
148#elif defined(USE_POSIX_SETLOCALE)
149 const char *saved_locale;
128#endif 150#endif
129 char number_fmt[8]; /* "%.XXg\0" */ 151 char number_fmt[8]; /* "%.XXg\0" */
130 int current_depth; 152 int current_depth;
@@ -369,7 +391,7 @@ static int json_destroy_config(lua_State *l)
369 json_config_t *cfg; 391 json_config_t *cfg;
370 392
371 cfg = lua_touserdata(l, 1); 393 cfg = lua_touserdata(l, 1);
372#ifdef USE_POSIX_LOCALE 394#ifdef USE_POSIX_USELOCALE
373 if (cfg->posix_locale) 395 if (cfg->posix_locale)
374 freelocale(cfg->posix_locale); 396 freelocale(cfg->posix_locale);
375#endif 397#endif
@@ -394,7 +416,7 @@ static void json_create_config(lua_State *l)
394 lua_setmetatable(l, -2); 416 lua_setmetatable(l, -2);
395 417
396 strbuf_init(&cfg->encode_buf, 0); 418 strbuf_init(&cfg->encode_buf, 0);
397#if USE_POSIX_LOCALE 419#ifdef USE_POSIX_USELOCALE
398 cfg->saved_locale = NULL; 420 cfg->saved_locale = NULL;
399 /* Must not lua_error() before cfg->posix_locale has been initialised */ 421 /* Must not lua_error() before cfg->posix_locale has been initialised */
400 cfg->posix_locale = newlocale(LC_ALL_MASK, "C", NULL); 422 cfg->posix_locale = newlocale(LC_ALL_MASK, "C", NULL);