예제 #1
0
int serialize_table_as_json(lua_sandbox* lsb,
                            serialization_data* data,
                            int isHash)
{
  int result = 0;
  lua_checkstack(lsb->lua, 2);
  lua_pushnil(lsb->lua);
  int had_output = 0;
  size_t start = 0;
  while (result == 0 && lua_next(lsb->lua, -2) != 0) {
    if (had_output) {
      if (appendc(&lsb->output, ',')) return 1;
    }
    start = lsb->output.pos;
    result = serialize_kvp_as_json(lsb, data, isHash);
    lua_pop(lsb->lua, 1); // Remove the value leaving the key on top for
                          // the next interation.
    if (start != lsb->output.pos) {
      had_output = 1;
    } else {
      had_output = 0;
    }
  }
  if (start != 0 && had_output == 0) { // remove the trailing comma
    size_t reset_pos = start - 1;
    if (lsb->output.data[reset_pos] == ',') {
      lsb->output.data[reset_pos] = 0;
      lsb->output.pos = reset_pos;
    }
  }
  return result;
}
예제 #2
0
int output(lua_State* lua)
{
    void* luserdata = lua_touserdata(lua, lua_upvalueindex(1));
    if (NULL == luserdata) {
        luaL_error(lua, "output() invalid lightuserdata");
    }
    lua_sandbox* lsb = (lua_sandbox*)luserdata;

    int n = lua_gettop(lua);
    if (n == 0) {
        luaL_error(lua, "output() must have at least one argument");
    }

    int result = 0;
    void* ud = NULL;
    for (int i = 1; result == 0 && i <= n; ++i) {
        switch (lua_type(lua, i)) {
        case LUA_TNUMBER:
            if (serialize_double(&lsb->m_output, lua_tonumber(lua, i))) {
                result = 1;
            }
            break;
        case LUA_TSTRING:
            if (dynamic_snprintf(&lsb->m_output, "%s", lua_tostring(lua, i))) {
                result = 1;
            }
            break;
        case LUA_TNIL:
            if (dynamic_snprintf(&lsb->m_output, "nil")) {
                result = 1;
            }
            break;
        case LUA_TBOOLEAN:
            if (dynamic_snprintf(&lsb->m_output, "%s",
                                 lua_toboolean(lsb->m_lua, i)
                                 ? "true" : "false")) {
                result = 1;
            }
            break;
        case LUA_TTABLE:
            if (!dynamic_snprintf(&lsb->m_output, "{")) {
                serialization_data data;
                data.m_globals = NULL;
                data.m_tables.m_size = 64;
                data.m_tables.m_pos = 0;
                data.m_tables.m_array = malloc(data.m_tables.m_size * sizeof(table_ref));
                if (data.m_tables.m_array == NULL) {
                    snprintf(lsb->m_error_message, ERROR_SIZE,
                             "json table serialization out of memory");
                    result = 1;
                } else {
                    lua_checkstack(lsb->m_lua, 2);
                    lua_getfield(lsb->m_lua, i, "_name");
                    if (lua_type(lsb->m_lua, -1) != LUA_TSTRING) {
                        lua_pop(lsb->m_lua, 1); // remove the failed _name result
                        lua_pushstring(lsb->m_lua, "table"); // add default name
                    }
                    lua_pushvalue(lsb->m_lua, i);
                    result = serialize_kvp_as_json(lsb, &data, 1);
                    if (result == 0) {
                        result = dynamic_snprintf(&lsb->m_output, "}\n");
                    }
                    lua_pop(lsb->m_lua, 2); // remove the name and copy of the table
                    free(data.m_tables.m_array);
                }
            } else {
                result = 1;
            }
            break;
        case LUA_TUSERDATA:
            ud = lua_touserdata(lua, i);
            if (heka_circular_buffer == userdata_type(lua, ud, i)) {
                if (output_circular_buffer(lua, (circular_buffer*)ud,
                                           &lsb->m_output)) {
                    result = 1;
                }
            }
            break;
        }
    }
    update_output_stats(lsb);
    if (result != 0
        || lsb->m_usage[USAGE_TYPE_OUTPUT][USAGE_STAT_CURRENT]
        > lsb->m_usage[USAGE_TYPE_OUTPUT][USAGE_STAT_LIMIT]) {
        if (lsb->m_error_message[0] == 0) {
            luaL_error(lua, "output_limit exceeded");
        }
        luaL_error(lua, lsb->m_error_message);
    }
    return 0;
}