diff options
author | Mark Pulford <mark@kyne.com.au> | 2011-10-07 23:55:49 +1030 |
---|---|---|
committer | Mark Pulford <mark@kyne.com.au> | 2011-10-07 23:55:49 +1030 |
commit | 049691cb11115fbdb750021556cad3507fad4e69 (patch) | |
tree | 3ef83227a086c2dbd70633a55a8425335a8e92fb | |
parent | 48c5cf183fa7cab608168fdec2406a1ca3cb2c11 (diff) | |
download | lua-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-- | Makefile | 8 | ||||
-rw-r--r-- | README | 12 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | lua-cjson-1.0.3-1.rockspec | 5 | ||||
-rw-r--r-- | lua_cjson.c | 38 |
5 files changed, 52 insertions, 13 deletions
@@ -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). |
27 | override 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. | ||
30 | override CFLAGS += -DUSE_POSIX_USELOCALE | ||
31 | #override CFLAGS += -DUSE_POSIX_SETLOCALE | ||
28 | 32 | ||
29 | INSTALL ?= install | 33 | INSTALL ?= install |
30 | 34 | ||
@@ -309,6 +309,18 @@ Lua CJSON will generate an error if asked to serialise Lua functions, | |||
309 | userdata, lightuserdata or threads. | 309 | userdata, lightuserdata or threads. |
310 | 310 | ||
311 | 311 | ||
312 | Locale handling | ||
313 | --------------- | ||
314 | |||
315 | Lua CJSON uses strtod() and snprintf() to perform numeric conversion | ||
316 | as they are usually well supported, fast and bug free. | ||
317 | |||
318 | To ensure JSON encoding/decoding works correctly for locales using | ||
319 | comma decimal separators, Lua CJSON must be compiled with either | ||
320 | USE_POSIX_USELOCALE or USE_POSIX_SETLOCALE. See the Makefile or the | ||
321 | rockspec for details. | ||
322 | |||
323 | |||
312 | References | 324 | References |
313 | ========== | 325 | ========== |
314 | 326 | ||
@@ -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); |