summaryrefslogtreecommitdiff
path: root/lua_cjson.c
diff options
context:
space:
mode:
Diffstat (limited to 'lua_cjson.c')
-rw-r--r--lua_cjson.c38
1 files changed, 30 insertions, 8 deletions
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);