diff options
Diffstat (limited to '')
| -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); |
