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;
}
Ejemplo n.º 2
0
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;
}