static void json_append_number(lua_State *l, json_config_t *cfg, strbuf_t *json, int lindex) { double num = lua_tonumber(l, lindex); int len; if (cfg->encode_invalid_numbers == 0) { /* Prevent encoding invalid numbers */ if (isinf(num) || isnan(num)) json_encode_exception(l, cfg, json, lindex, "must not be NaN or Inf"); } else if (cfg->encode_invalid_numbers == 1) { /* Encode invalid numbers, but handle "nan" separately * since some platforms may encode as "-nan". */ if (isnan(num)) { strbuf_append_mem(json, "nan", 3); return; } } else { /* Encode invalid numbers as "null" */ if (isinf(num) || isnan(num)) { strbuf_append_mem(json, "null", 4); return; } } strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision); strbuf_extend_length(json, len); }
static void json_append_number(lua_State *l, strbuf_t *json, int index, json_config_t *cfg) { double num = lua_tonumber(l, index); if (cfg->encode_refuse_badnum && (isinf(num) || isnan(num))) json_encode_exception(l, cfg, index, "must not be NaN or Inf"); /* Lowest double printed with %.14g is 21 characters long: * -1.7976931348623e+308 * * Use 32 to include the \0, and a few extra just in case.. */ strbuf_append_fmt(json, 32, cfg->number_fmt, num); }
static void json_append_number(lua_State *l, json_config_t *cfg, strbuf_t *json, int lindex) { int len; #if LUA_VERSION_NUM >= 503 if (lua_isinteger(l, lindex)) { lua_Integer num = lua_tointeger(l, lindex); strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); /* max length of int64 is 19 */ len = sprintf(strbuf_empty_ptr(json), LUA_INTEGER_FMT, num); strbuf_extend_length(json, len); return; } #endif double num = lua_tonumber(l, lindex); if (cfg->encode_invalid_numbers == 0) { /* Prevent encoding invalid numbers */ if (isinf(num) || isnan(num)) json_encode_exception(l, cfg, json, lindex, "must not be NaN or Infinity"); } else if (cfg->encode_invalid_numbers == 1) { /* Encode NaN/Infinity separately to ensure Javascript compatible * values are used. */ if (isnan(num)) { strbuf_append_mem(json, "NaN", 3); return; } if (isinf(num)) { if (num < 0) strbuf_append_mem(json, "-Infinity", 9); else strbuf_append_mem(json, "Infinity", 8); return; } } else { /* Encode invalid numbers as "null" */ if (isinf(num) || isnan(num)) { strbuf_append_mem(json, "null", 4); return; } } strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision); strbuf_extend_length(json, len); }
static void json_append_object(lua_State *l, json_config_t *cfg, strbuf_t *json) { int comma, keytype; json_encode_descend(l, cfg); /* Object */ strbuf_append_char(json, '{'); lua_pushnil(l); /* table, startkey */ comma = 0; while (lua_next(l, -2) != 0) { if (comma) strbuf_append_char(json, ','); else comma = 1; /* table, key, value */ keytype = lua_type(l, -2); if (keytype == LUA_TNUMBER) { strbuf_append_char(json, '"'); json_append_number(l, json, -2, cfg); strbuf_append_mem(json, "\":", 2); } else if (keytype == LUA_TSTRING) { json_append_string(l, json, -2); strbuf_append_char(json, ':'); } else { json_encode_exception(l, cfg, -2, "table key must be a number or string"); /* never returns */ } /* table, key, value */ json_append_data(l, cfg, json); lua_pop(l, 1); /* table, key */ } strbuf_append_char(json, '}'); cfg->current_depth--; }
/* Serialise Lua data into JSON string. */ static void json_append_data(lua_State *l, json_config_t *cfg, int current_depth, strbuf_t *json) { int len; switch (lua_type(l, -1)) { case LUA_TSTRING: json_append_string(l, json, -1); break; case LUA_TNUMBER: json_append_number(l, cfg, json, -1); break; case LUA_TBOOLEAN: if (lua_toboolean(l, -1)) strbuf_append_mem(json, "true", 4); else strbuf_append_mem(json, "false", 5); break; case LUA_TTABLE: current_depth++; json_check_encode_depth(l, cfg, current_depth, json); len = lua_array_length(l, cfg, json); if (len > 0) json_append_array(l, cfg, current_depth, json, len); else json_append_object(l, cfg, current_depth, json); break; case LUA_TNIL: strbuf_append_mem(json, "null", 4); break; case LUA_TLIGHTUSERDATA: if (lua_touserdata(l, -1) == NULL) { strbuf_append_mem(json, "null", 4); break; } default: /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, * and LUA_TLIGHTUSERDATA) cannot be serialised */ json_encode_exception(l, cfg, json, -1, "type not supported"); /* never returns */ } }
/* Find the size of the array on the top of the Lua stack * -1 object (not a pure array) * >=0 elements in array */ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json) { double k; int max; int items; max = 0; items = 0; lua_pushnil(l); /* table, startkey */ while (lua_next(l, -2) != 0) { /* table, key, value */ if (lua_type(l, -2) == LUA_TNUMBER && (k = lua_tonumber(l, -2))) { /* Integer >= 1 ? */ if (floor(k) == k && k >= 1) { if (k > max) max = k; items++; lua_pop(l, 1); continue; } } /* Must not be an array (non integer key) */ lua_pop(l, 2); return -1; } /* Encode excessively sparse arrays as objects (if enabled) */ if (cfg->encode_sparse_ratio > 0 && max > items * cfg->encode_sparse_ratio && max > cfg->encode_sparse_safe) { if (!cfg->encode_sparse_convert) json_encode_exception(l, cfg, json, -1, "excessively sparse array"); return -1; } return max; }