int serialize_kvp_as_json(lua_sandbox* lsb,
                          serialization_data* data,
                          int isHash)
{
  static const char array_start = '[', array_end = ']';
  static const char hash_start = '{', hash_end = '}';
  int kindex = -2, vindex = -1, result = 0;

  if (ignore_value_type_json(lsb, vindex)) return 0;
  if (ignore_key(lsb, kindex)) return 0;
  if (isHash) {
    if (serialize_data_as_json(lsb, kindex, &lsb->output)) return 1;
    if (appendc(&lsb->output, ':')) return 1;
  }

  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, 0);
      if (seen != NULL) {
        char start, end;
        lua_rawgeti(lsb->lua, vindex, 1);
        int hash = lua_isnil(lsb->lua, -1);
        lua_pop(lsb->lua, 1); // remove the test value
        if (hash) {
          start = hash_start;
          end = hash_end;
        } else {
          start = array_start;
          end = array_end;
        }
        if (appendc(&lsb->output, start)) return 1;
        if (serialize_table_as_json(lsb, data, hash)) return 1;
        if (appendc(&lsb->output, end)) return 1;
      } else {
        snprintf(lsb->error_message, LSB_ERROR_SIZE,
                 "serialize table out of memory");
        return 1;
      }
    } else {
      snprintf(lsb->error_message, LSB_ERROR_SIZE,
               "table contains an internal or circular reference");
      return 1;
    }
  } else {
    result = serialize_data_as_json(lsb, vindex, &lsb->output);
  }
  return result;
}
Beispiel #2
0
int serialize_kvp(lua_sandbox* lsb, serialization_data* data, size_t parent)
{
    int kindex = -2, vindex = -1;

    if (ignore_value_type(lsb, data, vindex)) return 0;
    int result = serialize_data(lsb, kindex, &lsb->m_output);
    if (result != 0) return result;

    size_t pos = data->m_keys.m_pos;
    if (dynamic_snprintf(&data->m_keys, "%s[%s]", data->m_keys.m_data + parent,
                         lsb->m_output.m_data)) {
        return 1;
    }

    fprintf(data->m_fh, "%s = ", data->m_keys.m_data + pos);
    if (lua_type(lsb->m_lua, vindex) == LUA_TTABLE) {
        const void* ptr = lua_topointer(lsb->m_lua, vindex);
        table_ref* seen = find_table_ref(&data->m_tables, ptr);
        if (seen == NULL) {
            seen = add_table_ref(&data->m_tables, ptr, pos);
            if (seen != NULL) {
                data->m_keys.m_pos += 1;
                fprintf(data->m_fh, "{}\n");
                result = serialize_table(lsb, data, pos);
            } else {
                snprintf(lsb->m_error_message, ERROR_SIZE,
                         "preserve table out of memory");
                return 1;
            }
        } else {
            data->m_keys.m_pos = pos;
            fprintf(data->m_fh, "%s\n", data->m_keys.m_data + seen->m_name_pos);
        }
    } else {
        data->m_keys.m_pos = pos;
        result = serialize_data(lsb, vindex, &lsb->m_output);
        if (result == 0) {
            fprintf(data->m_fh, "%s\n", lsb->m_output.m_data);
        }
    }
    return result;
}
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;
}