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 serialize_sax(lua_State* lua) { lsb_output_data* output = lua_touserdata(lua, -1); const char* key = lua_touserdata(lua, -2); sax_type type = sax_gettype(lua, -3); if (!key || !output) return 1; switch (type) { case SAX_WINDOW: { const struct sts_window* win = check_sax_window(lua, -3); size_t n = win->current_word.n_values; size_t w = win->current_word.w; size_t c = win->current_word.c; if (lsb_appendf(output, "if %s == nil then %s = sax.window.new(%" PRIuSIZE ", %" PRIuSIZE ", %" PRIuSIZE ") end\n", key, key, n, w, c)) return 1; if (!all_nans(win->values->buffer, win->current_word.n_values + 1)) { if (lsb_appendf(output, "%s:clear()\n%s:add({", key, key)) return 1; double* val = win->values->head; size_t n_values = 0; while (n_values < n) { if (n_values++ != 0 && lsb_appends(output, ",", 1)) return 1; if (lsb_serialize_double(output, *val)) return 1; if (++val == win->values->buffer_end) val = win->values->buffer; } if (lsb_appends(output, "})\n", 3)) return 1; } return 0; } case SAX_WORD: { const struct sts_word* a = check_sax_word(lua, -3); char* sax = sts_word_to_sax_string(a); if (!sax) { return luaL_error(lua, "memory allocation failed"); } if (lsb_appendf(output, "if %s == nil then %s = sax.word.new(\"%s\", %" PRIuSIZE ") end\n", key, key, sax, a->c)) { free(sax); return 1; } free(sax); return 0; } } return 1; }