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, 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); }
/* Serialise Lua data into JSON string. */ static void json_append_data(lua_State *l, struct luaL_serializer *cfg, int current_depth, strbuf_t *json) { struct luaL_field field; luaL_checkfield(l, cfg, -1, &field); switch (field.type) { case MP_UINT: return json_append_uint(cfg, json, field.ival); case MP_STR: case MP_BIN: return json_append_string(cfg, json, field.sval.data, field.sval.len); case MP_INT: return json_append_int(cfg, json, field.ival); case MP_FLOAT: return json_append_number(cfg, json, field.fval); case MP_DOUBLE: return json_append_number(cfg, json, field.dval); case MP_BOOL: if (field.bval) strbuf_append_mem(json, "true", 4); else strbuf_append_mem(json, "false", 5); break; case MP_NIL: json_append_nil(cfg, json); break; case MP_MAP: if (current_depth >= cfg->encode_max_depth) return json_append_nil(cfg, json); /* Limit nested maps */ json_append_object(l, cfg, current_depth, json); return; case MP_ARRAY: /* Array */ if (current_depth >= cfg->encode_max_depth) return json_append_nil(cfg, json); /* Limit nested arrays */ json_append_array(l, cfg, current_depth, json, field.size); return; case MP_EXT: /* handled by luaL_convertfield */ assert(false); return; } }
static void json_append_object(lua_State *l, struct luaL_serializer *cfg, int current_depth, strbuf_t *json) { int comma; /* 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; struct luaL_field field; luaL_checkfield(l, cfg, -2, &field); if (field.type == MP_UINT) { strbuf_append_char(json, '"'); json_append_uint(cfg, json, field.ival); strbuf_append_mem(json, "\":", 2); } else if (field.type == MP_INT) { strbuf_append_char(json, '"'); json_append_int(cfg, json, field.ival); strbuf_append_mem(json, "\":", 2); } else if (field.type == MP_STR) { json_append_string(cfg, json, field.sval.data, field.sval.len); strbuf_append_char(json, ':'); } else { luaL_error(l, "table key must be a number or string"); } /* table, key, value */ json_append_data(l, cfg, current_depth + 1, json); lua_pop(l, 1); /* table, key */ } strbuf_append_char(json, '}'); }
/* 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 */ } }
static void json_append_number(struct luaL_serializer *cfg, strbuf_t *json, lua_Number num) { if (isnan(num)) { strbuf_append_mem(json, "nan", 3); return; } int len; 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--; }
static size_t write_data(void *ptr, size_t size, size_t nmemb, void *data) { luv_curl_t *lc = (luv_curl_t *)data; if (lc->stat == CANCELLED) return 0; size *= nmemb; if (lc->retfp) size = fwrite(ptr, 1, size, lc->retfp); if (lc->retsb) strbuf_append_mem(lc->retsb, ptr, size); lc->rx += size; debug("write=%d", size); return size; }
static void json_append_nil(struct luaL_serializer *cfg, strbuf_t *json) { (void) cfg; strbuf_append_mem(json, "null", 4); }