| 1 | From 42064f63d05edf0769814734ada8ab1ce3435931 Mon Sep 17 00:00:00 2001
|
| 2 | From: Brian Maher <[email protected]>
|
| 3 | Date: Mon, 1 Jun 2015 12:37:01 -0700
|
| 4 | Subject: [PATCH 1/3] Allow empty array to be encoded with a metatable
|
| 5 | containing __is_cjson_array=true.
|
| 6 |
|
| 7 | ---
|
| 8 | lua_cjson.c | 30 ++++++++++++++++++++++++++++--
|
| 9 | 1 file changed, 28 insertions(+), 2 deletions(-)
|
| 10 |
|
| 11 | diff --git a/lua_cjson.c b/lua_cjson.c
|
| 12 | index c14a1c5..283e3af 100644
|
| 13 | |
| 14 | |
| 15 | @@ -494,9 +494,25 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
|
| 16 | int max;
|
| 17 | int items;
|
| 18 |
|
| 19 | - max = 0;
|
| 20 | + max = -1;
|
| 21 | items = 0;
|
| 22 |
|
| 23 | + if ( lua_getmetatable(l, -1) ) {
|
| 24 | + int is_array, has_is_array;
|
| 25 | +
|
| 26 | + lua_pushliteral(l, "__is_cjson_array");
|
| 27 | + lua_rawget(l, -2);
|
| 28 | + has_is_array = lua_isboolean(l, -1);
|
| 29 | + is_array = has_is_array && lua_toboolean(l, -1);
|
| 30 | + lua_pop(l, 2);
|
| 31 | +
|
| 32 | + if ( has_is_array && ! is_array ) {
|
| 33 | + return -1;
|
| 34 | + } else {
|
| 35 | + max = 0;
|
| 36 | + }
|
| 37 | + }
|
| 38 | +
|
| 39 | lua_pushnil(l);
|
| 40 | /* table, startkey */
|
| 41 | while (lua_next(l, -2) != 0) {
|
| 42 | @@ -685,7 +701,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg,
|
| 43 | current_depth++;
|
| 44 | json_check_encode_depth(l, cfg, current_depth, json);
|
| 45 | len = lua_array_length(l, cfg, json);
|
| 46 | - if (len > 0)
|
| 47 | + if (len >= 0)
|
| 48 | json_append_array(l, cfg, current_depth, json, len);
|
| 49 | else
|
| 50 | json_append_object(l, cfg, current_depth, json);
|
| 51 | @@ -1204,6 +1220,16 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
|
| 52 |
|
| 53 | /* Handle empty arrays */
|
| 54 | if (token.type == T_ARR_END) {
|
| 55 | + // Mark as array:
|
| 56 | + luaL_getmetatable(l, "cjson.array");
|
| 57 | + if ( lua_isnil(l, -1) ) {
|
| 58 | + lua_pop(l, 1);
|
| 59 | + luaL_newmetatable(l, "cjson.array");
|
| 60 | + lua_pushboolean(l, 1);
|
| 61 | + lua_setfield(l, -2, "__is_cjson_array");
|
| 62 | + }
|
| 63 | + lua_setmetatable(l, -2);
|
| 64 | +
|
| 65 | json_decode_ascend(json);
|
| 66 | return;
|
| 67 | }
|
| 68 | --
|
| 69 | 2.6.3
|
| 70 |
|
| 71 |
|
| 72 | From 514c4b4761ac0552182acbf25039930ddca70070 Mon Sep 17 00:00:00 2001
|
| 73 | From: Brian Maher <[email protected]>
|
| 74 | Date: Thu, 3 Sep 2015 12:33:33 -0700
|
| 75 | Subject: [PATCH 2/3] Replace __is_cjson_array with check for __name="array"
|
| 76 | and replace lightuserdata NULL with __name="null" meatable. This will allow
|
| 77 | better interchange with other modules that need to define "array" and "null"
|
| 78 | types. Note that you can also define custom implementations of "array" and
|
| 79 | "null" if you have access to the registry.
|
| 80 |
|
| 81 | ---
|
| 82 | lua_cjson.c | 65 ++++++++++++++++++++++++++++++++++++++++---------------------
|
| 83 | 1 file changed, 43 insertions(+), 22 deletions(-)
|
| 84 |
|
| 85 | diff --git a/lua_cjson.c b/lua_cjson.c
|
| 86 | index 283e3af..2140743 100644
|
| 87 | |
| 88 | |
| 89 | @@ -497,20 +497,13 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
|
| 90 | max = -1;
|
| 91 | items = 0;
|
| 92 |
|
| 93 | - if ( lua_getmetatable(l, -1) ) {
|
| 94 | - int is_array, has_is_array;
|
| 95 | -
|
| 96 | - lua_pushliteral(l, "__is_cjson_array");
|
| 97 | + if (lua_getmetatable(l, -1)) {
|
| 98 | + lua_pushliteral(l, "__name");
|
| 99 | lua_rawget(l, -2);
|
| 100 | - has_is_array = lua_isboolean(l, -1);
|
| 101 | - is_array = has_is_array && lua_toboolean(l, -1);
|
| 102 | - lua_pop(l, 2);
|
| 103 | -
|
| 104 | - if ( has_is_array && ! is_array ) {
|
| 105 | - return -1;
|
| 106 | - } else {
|
| 107 | + if (lua_isstring(l, -1) && strcmp("array", lua_tostring(l, -1)) == 0) {
|
| 108 | max = 0;
|
| 109 | }
|
| 110 | + lua_pop(l, 2);
|
| 111 | }
|
| 112 |
|
| 113 | lua_pushnil(l);
|
| 114 | @@ -698,6 +691,16 @@ static void json_append_data(lua_State *l, json_config_t *cfg,
|
| 115 | strbuf_append_mem(json, "false", 5);
|
| 116 | break;
|
| 117 | case LUA_TTABLE:
|
| 118 | + if (lua_getmetatable(l, -1)) {
|
| 119 | + lua_pushliteral(l, "__name");
|
| 120 | + lua_rawget(l, -2);
|
| 121 | + if (lua_isstring(l, -1) && strcmp("null", lua_tostring(l, -1)) == 0) {
|
| 122 | + strbuf_append_mem(json, "null", 4);
|
| 123 | + lua_pop(l, 2);
|
| 124 | + break;
|
| 125 | + }
|
| 126 | + lua_pop(l, 2);
|
| 127 | + }
|
| 128 | current_depth++;
|
| 129 | json_check_encode_depth(l, cfg, current_depth, json);
|
| 130 | len = lua_array_length(l, cfg, json);
|
| 131 | @@ -1221,13 +1224,7 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
|
| 132 | /* Handle empty arrays */
|
| 133 | if (token.type == T_ARR_END) {
|
| 134 | // Mark as array:
|
| 135 | - luaL_getmetatable(l, "cjson.array");
|
| 136 | - if ( lua_isnil(l, -1) ) {
|
| 137 | - lua_pop(l, 1);
|
| 138 | - luaL_newmetatable(l, "cjson.array");
|
| 139 | - lua_pushboolean(l, 1);
|
| 140 | - lua_setfield(l, -2, "__is_cjson_array");
|
| 141 | - }
|
| 142 | + luaL_getmetatable(l, "array");
|
| 143 | lua_setmetatable(l, -2);
|
| 144 |
|
| 145 | json_decode_ascend(json);
|
| 146 | @@ -1274,9 +1271,9 @@ static void json_process_value(lua_State *l, json_parse_t *json,
|
| 147 | break;;
|
| 148 | case T_NULL:
|
| 149 | /* In Lua, setting "t[k] = nil" will delete k from the table.
|
| 150 | - * Hence a NULL pointer lightuserdata object is used instead */
|
| 151 | - lua_pushlightuserdata(l, NULL);
|
| 152 | - break;;
|
| 153 | + * Hence a NULL userdata object is used instead */
|
| 154 | + luaL_getmetatable(l, "null");
|
| 155 | + break;
|
| 156 | default:
|
| 157 | json_throw_parse_error(l, json, "value", token);
|
| 158 | }
|
| 159 | @@ -1372,6 +1369,12 @@ static int json_protect_conversion(lua_State *l)
|
| 160 | return luaL_error(l, "Memory allocation error in CJSON protected call");
|
| 161 | }
|
| 162 |
|
| 163 | +static int json_null_tostring(lua_State *l)
|
| 164 | +{
|
| 165 | + lua_pushliteral(l, "null");
|
| 166 | + return 1;
|
| 167 | +}
|
| 168 | +
|
| 169 | /* Return cjson module table */
|
| 170 | static int lua_cjson_new(lua_State *l)
|
| 171 | {
|
| 172 | @@ -1392,6 +1395,24 @@ static int lua_cjson_new(lua_State *l)
|
| 173 | /* Initialise number conversions */
|
| 174 | fpconv_init();
|
| 175 |
|
| 176 | + /* Initialize "null" */
|
| 177 | + if ( luaL_newmetatable(l, "null") ) {
|
| 178 | + lua_createtable(l, 0, 2);
|
| 179 | + lua_pushliteral(l, "null");
|
| 180 | + lua_setfield(l, -2, "__name");
|
| 181 | + lua_pushcfunction(l, json_null_tostring);
|
| 182 | + lua_setfield(l, -2, "__tostring");
|
| 183 | + lua_setmetatable(l, -2);
|
| 184 | + }
|
| 185 | + lua_pop(l, 1);
|
| 186 | +
|
| 187 | + /* Initialize "array" metatable */
|
| 188 | + if ( luaL_newmetatable(l, "array") ) {
|
| 189 | + lua_pushliteral(l, "array");
|
| 190 | + lua_setfield(l, -2, "__name");
|
| 191 | + }
|
| 192 | + lua_pop(l, 1);
|
| 193 | +
|
| 194 | /* cjson module table */
|
| 195 | lua_newtable(l);
|
| 196 |
|
| 197 | @@ -1400,7 +1421,7 @@ static int lua_cjson_new(lua_State *l)
|
| 198 | luaL_setfuncs(l, reg, 1);
|
| 199 |
|
| 200 | /* Set cjson.null */
|
| 201 | - lua_pushlightuserdata(l, NULL);
|
| 202 | + luaL_getmetatable(l, "null");
|
| 203 | lua_setfield(l, -2, "null");
|
| 204 |
|
| 205 | /* Set module name / version fields */
|
| 206 | --
|
| 207 | 2.6.3
|
| 208 |
|
| 209 |
|
| 210 | From 438a71d35417453e2207f64f706d02f199525c7d Mon Sep 17 00:00:00 2001
|
| 211 | From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <[email protected]>
|
| 212 | Date: Tue, 8 Dec 2015 09:16:18 +0200
|
| 213 | Subject: [PATCH 3/3] fix empty array default encoding, and add meta __name for
|
| 214 | objects
|
| 215 |
|
| 216 | ---
|
| 217 | lua_cjson.c | 52 +++++++++++++++++++++++++++++++++-------------------
|
| 218 | 1 file changed, 33 insertions(+), 19 deletions(-)
|
| 219 |
|
| 220 | diff --git a/lua_cjson.c b/lua_cjson.c
|
| 221 | index 2140743..25952ec 100644
|
| 222 | |
| 223 | |
| 224 | @@ -493,17 +493,20 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
|
| 225 | double k;
|
| 226 | int max;
|
| 227 | int items;
|
| 228 | + int is_array = 0;
|
| 229 | + const char *mt_name;
|
| 230 |
|
| 231 | - max = -1;
|
| 232 | + max = 0;
|
| 233 | items = 0;
|
| 234 |
|
| 235 | if (lua_getmetatable(l, -1)) {
|
| 236 | lua_pushliteral(l, "__name");
|
| 237 | lua_rawget(l, -2);
|
| 238 | - if (lua_isstring(l, -1) && strcmp("array", lua_tostring(l, -1)) == 0) {
|
| 239 | - max = 0;
|
| 240 | - }
|
| 241 | + mt_name = lua_isstring(l, -1) ? lua_tostring(l, -1) : "";
|
| 242 | lua_pop(l, 2);
|
| 243 | + if (strcmp("object", mt_name) == 0)
|
| 244 | + return -1;
|
| 245 | + is_array = strcmp("array", mt_name) == 0;
|
| 246 | }
|
| 247 |
|
| 248 | lua_pushnil(l);
|
| 249 | @@ -521,6 +524,10 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
|
| 250 | continue;
|
| 251 | }
|
| 252 | }
|
| 253 | + if (is_array) {
|
| 254 | + lua_pop(l, 1);
|
| 255 | + continue;
|
| 256 | + }
|
| 257 |
|
| 258 | /* Must not be an array (non integer key) */
|
| 259 | lua_pop(l, 2);
|
| 260 | @@ -537,6 +544,10 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
|
| 261 | return -1;
|
| 262 | }
|
| 263 |
|
| 264 | + /* Backwards compatibility - encode untyped zero length table as object */
|
| 265 | + if (!is_array && max == 0)
|
| 266 | + return -1;
|
| 267 | +
|
| 268 | return max;
|
| 269 | }
|
| 270 |
|
| 271 | @@ -1166,6 +1177,8 @@ static void json_parse_object_context(lua_State *l, json_parse_t *json)
|
| 272 | json_decode_descend(l, json, 3);
|
| 273 |
|
| 274 | lua_newtable(l);
|
| 275 | + luaL_getmetatable(l, "cjson.object");
|
| 276 | + lua_setmetatable(l, -2);
|
| 277 |
|
| 278 | json_next_token(json, &token);
|
| 279 |
|
| 280 | @@ -1218,15 +1231,13 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
|
| 281 | json_decode_descend(l, json, 2);
|
| 282 |
|
| 283 | lua_newtable(l);
|
| 284 | + luaL_getmetatable(l, "cjson.array");
|
| 285 | + lua_setmetatable(l, -2);
|
| 286 |
|
| 287 | json_next_token(json, &token);
|
| 288 |
|
| 289 | /* Handle empty arrays */
|
| 290 | if (token.type == T_ARR_END) {
|
| 291 | - // Mark as array:
|
| 292 | - luaL_getmetatable(l, "array");
|
| 293 | - lua_setmetatable(l, -2);
|
| 294 | -
|
| 295 | json_decode_ascend(json);
|
| 296 | return;
|
| 297 | }
|
| 298 | @@ -1272,7 +1283,7 @@ static void json_process_value(lua_State *l, json_parse_t *json,
|
| 299 | case T_NULL:
|
| 300 | /* In Lua, setting "t[k] = nil" will delete k from the table.
|
| 301 | * Hence a NULL userdata object is used instead */
|
| 302 | - luaL_getmetatable(l, "null");
|
| 303 | + luaL_getmetatable(l, "cjson.null");
|
| 304 | break;
|
| 305 | default:
|
| 306 | json_throw_parse_error(l, json, "value", token);
|
| 307 | @@ -1395,8 +1406,11 @@ static int lua_cjson_new(lua_State *l)
|
| 308 | /* Initialise number conversions */
|
| 309 | fpconv_init();
|
| 310 |
|
| 311 | + /* cjson module table */
|
| 312 | + lua_newtable(l);
|
| 313 | +
|
| 314 | /* Initialize "null" */
|
| 315 | - if ( luaL_newmetatable(l, "null") ) {
|
| 316 | + if ( luaL_newmetatable(l, "cjson.null") ) {
|
| 317 | lua_createtable(l, 0, 2);
|
| 318 | lua_pushliteral(l, "null");
|
| 319 | lua_setfield(l, -2, "__name");
|
| 320 | @@ -1404,26 +1418,26 @@ static int lua_cjson_new(lua_State *l)
|
| 321 | lua_setfield(l, -2, "__tostring");
|
| 322 | lua_setmetatable(l, -2);
|
| 323 | }
|
| 324 | - lua_pop(l, 1);
|
| 325 | + lua_setfield(l, -2, "null");
|
| 326 |
|
| 327 | /* Initialize "array" metatable */
|
| 328 | - if ( luaL_newmetatable(l, "array") ) {
|
| 329 | + if ( luaL_newmetatable(l, "cjson.array") ) {
|
| 330 | lua_pushliteral(l, "array");
|
| 331 | lua_setfield(l, -2, "__name");
|
| 332 | }
|
| 333 | - lua_pop(l, 1);
|
| 334 | + lua_setfield(l, -2, "array");
|
| 335 |
|
| 336 | - /* cjson module table */
|
| 337 | - lua_newtable(l);
|
| 338 | + /* Initialize "object" metatable */
|
| 339 | + if ( luaL_newmetatable(l, "cjson.object") ) {
|
| 340 | + lua_pushliteral(l, "object");
|
| 341 | + lua_setfield(l, -2, "__name");
|
| 342 | + }
|
| 343 | + lua_setfield(l, -2, "object");
|
| 344 |
|
| 345 | /* Register functions with config data as upvalue */
|
| 346 | json_create_config(l);
|
| 347 | luaL_setfuncs(l, reg, 1);
|
| 348 |
|
| 349 | - /* Set cjson.null */
|
| 350 | - luaL_getmetatable(l, "null");
|
| 351 | - lua_setfield(l, -2, "null");
|
| 352 | -
|
| 353 | /* Set module name / version fields */
|
| 354 | lua_pushliteral(l, CJSON_MODNAME);
|
| 355 | lua_setfield(l, -2, "_NAME");
|
| 356 | --
|
| 357 | 2.6.3
|
| 358 |
|