static int serialize_bloom_filter(lua_State *lua) { lsb_output_buffer* ob = lua_touserdata(lua, -1); const char *key = lua_touserdata(lua, -2); bloom_filter* bf = lua_touserdata(lua, -3); if (!(ob && key && bf)) { return 1; } if (lsb_outputf(ob, "if %s == nil then %s = bloom_filter.new(%u, %g) end\n", key, key, (unsigned)bf->items, bf->probability)) { return 1; } if (lsb_outputf(ob, "%s:fromstring(%u, \"", key, (unsigned)bf->cnt)) { return 1; } if (lsb_serialize_binary(ob, bf->data, bf->bytes)) return 1; if (lsb_outputs(ob, "\")\n", 3)) { return 1; } return 0; }
static lsb_err_value serialize_data(lsb_lua_sandbox *lsb, int index, lsb_output_buffer *ob) { lsb_err_value ret = NULL; ob->pos = 0; // clear the buffer switch (lua_type(lsb->lua, index)) { case LUA_TNUMBER: ret = lsb_serialize_double(ob, lua_tonumber(lsb->lua, index)); break; case LUA_TSTRING: // The stack is cleaned up on failure by preserve_global_data // but for clarity it is incrementally cleaned up anyway. lua_checkstack(lsb->lua, 4); lua_getglobal(lsb->lua, LUA_STRLIBNAME); lua_getfield(lsb->lua, -1, "format"); if (!lua_isfunction(lsb->lua, -1)) { snprintf(lsb->error_message, LSB_ERROR_SIZE, "serialize_data cannot access the string format function"); lua_pop(lsb->lua, 2); // Remove the bogus format function and // string table. return LSB_ERR_LUA; } lua_pushstring(lsb->lua, "%q"); lua_pushvalue(lsb->lua, index - 3); if (lua_pcall(lsb->lua, 2, 1, 0) == 0) { const char* em = lua_tostring(lsb->lua, -1); ret = lsb_outputf(ob, "%s", em ? em : LSB_NIL_ERROR); if (ret) { lua_pop(lsb->lua, 1); // Remove the string table. return ret; } } else { int len = snprintf(lsb->error_message, LSB_ERROR_SIZE, "serialize_data '%s'", lua_tostring(lsb->lua, -1)); if (len >= LSB_ERROR_SIZE || len < 0) { lsb->error_message[LSB_ERROR_SIZE - 1] = 0; } lua_pop(lsb->lua, 2); // Remove the error message and the string // table. return LSB_ERR_LUA; } lua_pop(lsb->lua, 2); // Remove the pcall result and the string table. break; case LUA_TBOOLEAN: ret = lsb_outputf(ob, "%s", lua_toboolean(lsb->lua, index) ? "true" : "false"); break; default: snprintf(lsb->error_message, LSB_ERROR_SIZE, "serialize_data cannot preserve type '%s'", lua_typename(lsb->lua, lua_type(lsb->lua, index))); ret = LSB_ERR_LUA; } return ret; }
static int ud_output(lua_State *lua) { lsb_output_buffer *ob = lua_touserdata(lua, -1); test_ud *ud = lua_touserdata(lua, -2); if (!(ob && ud)) {return 1; } return lsb_outputf(ob, "%s", ud->name) == NULL ? 0 : 1; }
static int serialize_hyperloglog(lua_State *lua) { lsb_output_buffer *ob = lua_touserdata(lua, -1); const char *key = lua_touserdata(lua, -2); hyperloglog *hll = lua_touserdata(lua, -3); if (!(ob && key && hll)) return 1; if (lsb_outputf(ob, "if %s == nil then %s = hyperloglog.new() end\n", key, key)) { return 1; } if (lsb_outputf(ob, "%s:fromstring(\"", key)) return 1; if (lsb_serialize_binary(ob, hll, sizeof(hyperloglog) - 1)) return 1; if (lsb_outputs(ob, "\")\n", 3)) return 1; return 0; }
static int ud_serialize(lua_State *lua) { lsb_output_buffer *ob = lua_touserdata(lua, -1); const char *key = lua_touserdata(lua, -2); test_ud *ud = lua_touserdata(lua, -3); if (!(ob && key && ud)) {return 1;} return lsb_outputf(ob, "if %s == nil then %s = ud.new('%s') end\n", key, key, ud->name) == NULL ? 0 : 1; }
static lsb_err_value serialize_kvp(lsb_lua_sandbox *lsb, serialization_data *data, size_t parent) { lsb_err_value ret = NULL; lua_CFunction fp = NULL; int kindex = -2, vindex = -1; if (ignore_value_type(lsb, data, vindex, &fp)) { return ret; } ret = serialize_data(lsb, kindex, &lsb->output); if (ret) { return ret; } size_t pos = data->keys.pos; ret = lsb_outputf(&data->keys, "%s[%s]", data->keys.buf + parent, lsb->output.buf); if (ret) return ret; if (lua_type(lsb->lua, vindex) == LUA_TTABLE) { const void *ptr = lua_topointer(lsb->lua, vindex); table_ref *seen = find_table_ref(&data->tables, ptr); if (seen == NULL) { seen = add_table_ref(&data->tables, ptr, pos); if (seen != NULL) { data->keys.pos += 1; fprintf(data->fh, "%s = {}\n", data->keys.buf + pos); ret = serialize_table(lsb, data, pos); } else { snprintf(lsb->error_message, LSB_ERROR_SIZE, "lsb_serialize preserve table out of memory"); return LSB_ERR_UTIL_OOM; } } else { fprintf(data->fh, "%s = ", data->keys.buf + pos); data->keys.pos = pos; fprintf(data->fh, "%s\n", data->keys.buf + seen->name_pos); } } else if (lua_type(lsb->lua, vindex) == LUA_TUSERDATA) { void *ud = lua_touserdata(lsb->lua, vindex); table_ref *seen = find_table_ref(&data->tables, ud); if (seen == NULL) { seen = add_table_ref(&data->tables, ud, pos); if (seen != NULL) { data->keys.pos += 1; lua_pushlightuserdata(lsb->lua, data->keys.buf + pos); lua_pushlightuserdata(lsb->lua, &lsb->output); lsb->output.pos = 0; int result = fp(lsb->lua); lua_pop(lsb->lua, 2); // remove the key and the output if (!result) { size_t n = fwrite(lsb->output.buf, 1, lsb->output.pos, data->fh); if (n != lsb->output.pos) { snprintf(lsb->error_message, LSB_ERROR_SIZE, "lsb_serialize failed %s", data->keys.buf + pos); return LSB_ERR_LUA; } } } else { snprintf(lsb->error_message, LSB_ERROR_SIZE, "lsb_serialize out of memory %s", data->keys.buf + pos); return LSB_ERR_UTIL_OOM; } } else { fprintf(data->fh, "%s = ", data->keys.buf + pos); data->keys.pos = pos; fprintf(data->fh, "%s\n", data->keys.buf + seen->name_pos); } } else { fprintf(data->fh, "%s = ", data->keys.buf + pos); data->keys.pos = pos; ret = serialize_data(lsb, vindex, &lsb->output); if (!ret) { fprintf(data->fh, "%s\n", lsb->output.buf); } } return ret; }
lsb_err_value lsb_outputfd(lsb_output_buffer *b, double d) { if (!b) return LSB_ERR_UTIL_NULL; if (d < INT_MIN || d > INT_MAX) { return lsb_outputf(b, "%0.17g", d); } const int precision = 8; const unsigned magnitude = 100000000; char buffer[20]; char *p = buffer; int negative = 0; if (d < 0) { negative = 1; d = -d; } int number = (int)d; double tmp = (d - number) * magnitude; unsigned fraction = (unsigned)tmp; double diff = tmp - fraction; if (diff > 0.5) { ++fraction; if (fraction >= magnitude) { fraction = 0; ++number; } } else if (diff == 0.5 && ((fraction == 0) || (fraction & 1))) { // bankers rounding ++fraction; } // decimal fraction if (fraction != 0) { int nodigits = 1; char c = 0; for (int x = 0; x < precision; ++x) { c = fraction % 10; if (!(c == 0 && nodigits)) { *p++ = c + '0'; nodigits = 0; } fraction /= 10; } *p++ = '.'; } // number do { *p++ = (number % 10) + '0'; number /= 10; } while (number > 0); lsb_err_value ret = lsb_expand_output_buffer(b, (p - buffer) + negative); if (!ret) { if (negative) { b->buf[b->pos++] = '-'; } do { --p; b->buf[b->pos++] = *p; } while (p != buffer); b->buf[b->pos] = 0; } return ret; }