|
| 1 | +diff --git a/CMakeLists.txt b/CMakeLists.txt |
| 2 | +index c17239b..bd95e5a 100644 |
| 3 | +--- a/CMakeLists.txt |
| 4 | ++++ b/CMakeLists.txt |
| 5 | +@@ -68,9 +68,15 @@ else() |
| 6 | + set(_lua_module_dir "${_lua_lib_dir}/lua/5.1") |
| 7 | + endif() |
| 8 | + |
| 9 | +-add_library(cjson MODULE lua_cjson.c strbuf.c ${FPCONV_SOURCES}) |
| 10 | +-set_target_properties(cjson PROPERTIES PREFIX "") |
| 11 | +-target_link_libraries(cjson ${_MODULE_LINK}) |
| 12 | +-install(TARGETS cjson DESTINATION "${_lua_module_dir}") |
| 13 | +- |
| 14 | ++add_library(libcjson STATIC lua_cjson.c strbuf.c ${FPCONV_SOURCES}) |
| 15 | ++set_target_properties(libcjson PROPERTIES PREFIX "") |
| 16 | ++target_link_libraries(libcjson ${_MODULE_LINK}) |
| 17 | ++INSTALL( |
| 18 | ++ TARGETS libcjson |
| 19 | ++ ARCHIVE DESTINATION lib |
| 20 | ++ LIBRARY DESTINATION lib |
| 21 | ++ COMPONENT library |
| 22 | ++) |
| 23 | ++set(include_items dtoa_config.h fpconv.h strbuf.h lua_cjson.h) |
| 24 | ++install(FILES ${include_items} DESTINATION "include/cjson") |
| 25 | + # vi:ai et sw=4 ts=4: |
| 26 | +diff --git a/fpconv.c b/fpconv.c |
| 27 | +index 7990831..49b83ae 100644 |
| 28 | +--- a/fpconv.c |
| 29 | ++++ b/fpconv.c |
| 30 | +@@ -98,7 +98,7 @@ static int strtod_buffer_size(const char *s) |
| 31 | + while (valid_number_character(*p)) |
| 32 | + p++; |
| 33 | + |
| 34 | +- return p - s; |
| 35 | ++ return (int)(p - s); |
| 36 | + } |
| 37 | + |
| 38 | + /* Similar to strtod(), but must be passed the current locale's decimal point |
| 39 | +diff --git a/fpconv.h b/fpconv.h |
| 40 | +index 0124908..02017be 100644 |
| 41 | +--- a/fpconv.h |
| 42 | ++++ b/fpconv.h |
| 43 | +@@ -6,13 +6,19 @@ |
| 44 | + * -1.7976931348623e+308 */ |
| 45 | + # define FPCONV_G_FMT_BUFSIZE 32 |
| 46 | + |
| 47 | ++#ifdef _MSC_VER |
| 48 | ++#define snprintf _snprintf |
| 49 | ++#undef inline |
| 50 | ++#define inline __inline |
| 51 | ++#endif |
| 52 | ++ |
| 53 | + #ifdef USE_INTERNAL_FPCONV |
| 54 | +-static inline void fpconv_init() |
| 55 | ++static void fpconv_init() |
| 56 | + { |
| 57 | + /* Do nothing - not required */ |
| 58 | + } |
| 59 | + #else |
| 60 | +-extern inline void fpconv_init(); |
| 61 | ++extern void fpconv_init(); |
| 62 | + #endif |
| 63 | + |
| 64 | + extern int fpconv_g_fmt(char*, double, int); |
| 65 | +diff --git a/lua_cjson.c b/lua_cjson.c |
| 66 | +index ca5b88d..e7633be 100644 |
| 67 | +--- a/lua_cjson.c |
| 68 | ++++ b/lua_cjson.c |
| 69 | +@@ -40,9 +40,9 @@ |
| 70 | + #include <string.h> |
| 71 | + #include <math.h> |
| 72 | + #include <limits.h> |
| 73 | +-#include <lua.h> |
| 74 | +-#include <lauxlib.h> |
| 75 | + |
| 76 | ++#include "lua.h" |
| 77 | ++#include "lauxlib.h" |
| 78 | + #include "strbuf.h" |
| 79 | + #include "fpconv.h" |
| 80 | + |
| 81 | +@@ -54,9 +54,12 @@ |
| 82 | + #define CJSON_VERSION "2.1devel" |
| 83 | + #endif |
| 84 | + |
| 85 | +-/* Workaround for Solaris platforms missing isinf() */ |
| 86 | +-#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF)) |
| 87 | +-#define isinf(x) (!isnan(x) && isnan((x) - (x))) |
| 88 | ++#ifdef _WIN32 |
| 89 | ++#define __strncasecmp strnicmp |
| 90 | ++#define isnan(x) ((x) != (x)) |
| 91 | ++#define isinf(x) (!isnan(x) && isnan(x - x)) |
| 92 | ++#else |
| 93 | ++#define __strncasecmp strncasecmp |
| 94 | + #endif |
| 95 | + |
| 96 | + #define DEFAULT_SPARSE_CONVERT 0 |
| 97 | +@@ -68,6 +71,7 @@ |
| 98 | + #define DEFAULT_DECODE_INVALID_NUMBERS 1 |
| 99 | + #define DEFAULT_ENCODE_KEEP_BUFFER 1 |
| 100 | + #define DEFAULT_ENCODE_NUMBER_PRECISION 14 |
| 101 | ++#define DEFAULT_DECODE_LUA_NIL 1 |
| 102 | + |
| 103 | + #ifdef DISABLE_INVALID_NUMBERS |
| 104 | + #undef DEFAULT_DECODE_INVALID_NUMBERS |
| 105 | +@@ -127,6 +131,7 @@ typedef struct { |
| 106 | + |
| 107 | + int decode_invalid_numbers; |
| 108 | + int decode_max_depth; |
| 109 | ++ int decode_lua_nil; /* 1 => use Lua nil for NULL */ |
| 110 | + } json_config_t; |
| 111 | + |
| 112 | + typedef struct { |
| 113 | +@@ -222,7 +227,7 @@ static int json_integer_option(lua_State *l, int optindex, int *setting, |
| 114 | + int value; |
| 115 | + |
| 116 | + if (!lua_isnil(l, optindex)) { |
| 117 | +- value = luaL_checkinteger(l, optindex); |
| 118 | ++ value = (int)luaL_checkinteger(l, optindex); |
| 119 | + snprintf(errmsg, sizeof(errmsg), "expected integer between %d and %d", min, max); |
| 120 | + luaL_argcheck(l, min <= value && value <= max, 1, errmsg); |
| 121 | + *setting = value; |
| 122 | +@@ -356,6 +361,15 @@ static int json_cfg_decode_invalid_numbers(lua_State *l) |
| 123 | + return 1; |
| 124 | + } |
| 125 | + |
| 126 | ++static int json_cfg_decode_lua_nil(lua_State *l) |
| 127 | ++{ |
| 128 | ++ json_config_t *cfg = json_arg_init(l, 1); |
| 129 | ++ |
| 130 | ++ json_enum_option(l, 1, &cfg->decode_lua_nil, NULL, 1); |
| 131 | ++ |
| 132 | ++ return 1; |
| 133 | ++} |
| 134 | ++ |
| 135 | + static int json_destroy_config(lua_State *l) |
| 136 | + { |
| 137 | + json_config_t *cfg; |
| 138 | +@@ -390,6 +404,7 @@ static void json_create_config(lua_State *l) |
| 139 | + cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS; |
| 140 | + cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; |
| 141 | + cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION; |
| 142 | ++ cfg->decode_lua_nil = DEFAULT_DECODE_LUA_NIL; |
| 143 | + |
| 144 | + #if DEFAULT_ENCODE_KEEP_BUFFER > 0 |
| 145 | + strbuf_init(&cfg->encode_buf, 0); |
| 146 | +@@ -471,7 +486,7 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex) |
| 147 | + * This buffer is reused constantly for small strings |
| 148 | + * If there are any excess pages, they won't be hit anyway. |
| 149 | + * This gains ~5% speedup. */ |
| 150 | +- strbuf_ensure_empty_length(json, len * 6 + 2); |
| 151 | ++ strbuf_ensure_empty_length(json, (int)len * 6 + 2); |
| 152 | + |
| 153 | + strbuf_append_char_unsafe(json, '\"'); |
| 154 | + for (i = 0; i < len; i++) { |
| 155 | +@@ -592,12 +607,20 @@ static void json_append_number(lua_State *l, json_config_t *cfg, |
| 156 | + if (cfg->encode_invalid_numbers == 0) { |
| 157 | + /* Prevent encoding invalid numbers */ |
| 158 | + if (isinf(num) || isnan(num)) |
| 159 | +- json_encode_exception(l, cfg, json, lindex, "must not be NaN or Inf"); |
| 160 | ++ json_encode_exception(l, cfg, json, lindex, |
| 161 | ++ "must not be NaN or Infinity"); |
| 162 | + } else if (cfg->encode_invalid_numbers == 1) { |
| 163 | +- /* Encode invalid numbers, but handle "nan" separately |
| 164 | +- * since some platforms may encode as "-nan". */ |
| 165 | ++ /* Encode NaN/Infinity separately to ensure Javascript compatible |
| 166 | ++ * values are used. */ |
| 167 | + if (isnan(num)) { |
| 168 | +- strbuf_append_mem(json, "nan", 3); |
| 169 | ++ strbuf_append_mem(json, "NaN", 3); |
| 170 | ++ return; |
| 171 | ++ } |
| 172 | ++ if (isinf(num)) { |
| 173 | ++ if (num < 0) |
| 174 | ++ strbuf_append_mem(json, "-Infinity", 9); |
| 175 | ++ else |
| 176 | ++ strbuf_append_mem(json, "Infinity", 8); |
| 177 | + return; |
| 178 | + } |
| 179 | + } else { |
| 180 | +@@ -876,7 +899,7 @@ static void json_set_token_error(json_token_t *token, json_parse_t *json, |
| 181 | + const char *errtype) |
| 182 | + { |
| 183 | + token->type = T_ERROR; |
| 184 | +- token->index = json->ptr - json->data; |
| 185 | ++ token->index = (int)(json->ptr - json->data); |
| 186 | + token->value.string = errtype; |
| 187 | + } |
| 188 | + |
| 189 | +@@ -981,9 +1004,9 @@ static int json_is_invalid_number(json_parse_t *json) |
| 190 | + } |
| 191 | + |
| 192 | + /* Reject inf/nan */ |
| 193 | +- if (!strncasecmp(p, "inf", 3)) |
| 194 | ++ if (!__strncasecmp(p, "inf", 3)) |
| 195 | + return 1; |
| 196 | +- if (!strncasecmp(p, "nan", 3)) |
| 197 | ++ if (!__strncasecmp(p, "nan", 3)) |
| 198 | + return 1; |
| 199 | + |
| 200 | + /* Pass all other numbers which may still be invalid, but |
| 201 | +@@ -1025,7 +1048,7 @@ static void json_next_token(json_parse_t *json, json_token_t *token) |
| 202 | + |
| 203 | + /* Store location of new token. Required when throwing errors |
| 204 | + * for unexpected tokens (syntax errors). */ |
| 205 | +- token->index = json->ptr - json->data; |
| 206 | ++ token->index = (int)(json->ptr - json->data); |
| 207 | + |
| 208 | + /* Don't advance the pointer for an error or the end */ |
| 209 | + if (token->type == T_ERROR) { |
| 210 | +@@ -1239,9 +1262,16 @@ static void json_process_value(lua_State *l, json_parse_t *json, |
| 211 | + json_parse_array_context(l, json); |
| 212 | + break;; |
| 213 | + case T_NULL: |
| 214 | +- /* In Lua, setting "t[k] = nil" will delete k from the table. |
| 215 | +- * Hence a NULL pointer lightuserdata object is used instead */ |
| 216 | +- lua_pushlightuserdata(l, NULL); |
| 217 | ++ if (json->cfg->decode_lua_nil) |
| 218 | ++ { |
| 219 | ++ lua_pushnil(l); |
| 220 | ++ } |
| 221 | ++ else |
| 222 | ++ { |
| 223 | ++ /* In Lua, setting "t[k] = nil" will delete k from the table. |
| 224 | ++ * Hence a NULL pointer lightuserdata object is used instead */ |
| 225 | ++ lua_pushlightuserdata(l, NULL); |
| 226 | ++ } |
| 227 | + break;; |
| 228 | + default: |
| 229 | + json_throw_parse_error(l, json, "value", token); |
| 230 | +@@ -1272,7 +1302,7 @@ static int json_decode(lua_State *l) |
| 231 | + /* Ensure the temporary buffer can hold the entire string. |
| 232 | + * This means we no longer need to do length checks since the decoded |
| 233 | + * string must be smaller than the entire json string */ |
| 234 | +- json.tmp = strbuf_new(json_len); |
| 235 | ++ json.tmp = strbuf_new((int)json_len); |
| 236 | + |
| 237 | + json_next_token(&json, &token); |
| 238 | + json_process_value(l, &json, &token); |
| 239 | +@@ -1351,6 +1381,7 @@ static int lua_cjson_new(lua_State *l) |
| 240 | + { "encode_keep_buffer", json_cfg_encode_keep_buffer }, |
| 241 | + { "encode_invalid_numbers", json_cfg_encode_invalid_numbers }, |
| 242 | + { "decode_invalid_numbers", json_cfg_decode_invalid_numbers }, |
| 243 | ++ { "decode_lua_nil", json_cfg_decode_lua_nil }, |
| 244 | + { "new", lua_cjson_new }, |
| 245 | + { NULL, NULL } |
| 246 | + }; |
| 247 | +diff --git a/lua_cjson.h b/lua_cjson.h |
| 248 | +new file mode 100644 |
| 249 | +index 0000000..4d3b1e7 |
| 250 | +--- /dev/null |
| 251 | ++++ b/lua_cjson.h |
| 252 | +@@ -0,0 +1,12 @@ |
| 253 | ++ |
| 254 | ++#ifndef __LUA_CJSON_H_ |
| 255 | ++#define __LUA_CJSON_H_ |
| 256 | ++ |
| 257 | ++#include "lua.h" |
| 258 | ++ |
| 259 | ++#define USE_INTERNAL_FPCONV |
| 260 | ++ |
| 261 | ++int luaopen_cjson(lua_State *l); |
| 262 | ++int luaopen_cjson_safe(lua_State *l); |
| 263 | ++ |
| 264 | ++#endif // __LUA_CJSON_H_ |
| 265 | +diff --git a/strbuf.h b/strbuf.h |
| 266 | +index d861108..eb09da9 100644 |
| 267 | +--- a/strbuf.h |
| 268 | ++++ b/strbuf.h |
| 269 | +@@ -74,6 +74,12 @@ extern void strbuf_append_string(strbuf_t *s, const char *str); |
| 270 | + static void strbuf_append_char(strbuf_t *s, const char c); |
| 271 | + static void strbuf_ensure_null(strbuf_t *s); |
| 272 | + |
| 273 | ++#ifdef _MSC_VER |
| 274 | ++#define snprintf _snprintf |
| 275 | ++#undef inline |
| 276 | ++#define inline __inline |
| 277 | ++#endif |
| 278 | ++ |
| 279 | + /* Reset string for before use */ |
| 280 | + static inline void strbuf_reset(strbuf_t *s) |
| 281 | + { |
0 commit comments