예제 #1
0
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;
}
예제 #3
0
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;
}
예제 #5
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;
}
예제 #7
0
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;
}