Files
fs2open.github.com/code/scripting/util/LuaValueSerializer.cpp
T
Goober5000 e90416e199 Several coverity fixes (#6232)
* coverity - using `std::move` instead of copying, and change some parameters from value to reference

* coverity - fix or mark potential copy-paste mistakes

* coverity - various checking of parameter and return values

* coverity - miscellaneous fixes, and change some 'intentional' markers to 'false positive' markers
2024-07-06 12:51:31 +02:00

102 lines
2.8 KiB
C++

#include "LuaValueSerializer.h"
#include "scripting/lua/LuaTable.h"
namespace scripting {
namespace util {
LuaValueSerializer::LuaValueSerializer(luacpp::LuaValue value) : m_value(std::move(value)) {}
SCP_vector<uint8_t> LuaValueSerializer::serialize() const
{
std::unique_ptr<json_t> serializedJson(toJson());
const auto json = json_dump_string(serializedJson.get(), JSON_ENCODE_ANY | JSON_COMPACT);
SCP_vector<uint8_t> data;
data.reserve(json.size() + 1);
// Add a tiny header describing the following data for future proofing.
data.push_back(static_cast<uint8_t>(SerializationType::PlainJson));
std::transform(json.cbegin(), json.cend(), std::back_inserter(data), [](char c) {
return static_cast<uint8_t>(c);
});
return data;
}
json_t* LuaValueSerializer::toJson() const
{
switch (m_value.getValueType()) {
case luacpp::ValueType::NIL:
return json_null();
case luacpp::ValueType::BOOLEAN:
return json_boolean(m_value.getValue<bool>());
case luacpp::ValueType::STRING: {
const auto string = m_value.getValue<SCP_string>();
return json_stringn(string.c_str(), string.size());
}
case luacpp::ValueType::NUMBER:
return json_real(m_value.getValue<double>());
case luacpp::ValueType::TABLE:
return tableToJson();
case luacpp::ValueType::NONE:
case luacpp::ValueType::USERDATA:
case luacpp::ValueType::FUNCTION:
case luacpp::ValueType::LIGHTUSERDATA:
case luacpp::ValueType::THREAD:
default:
throw std::runtime_error("Unsupported value type!");
}
}
json_t* LuaValueSerializer::tableToJson() const
{
luacpp::LuaTable tableVal;
tableVal.setReference(m_value.getReference());
auto testVal = tableVal.getValue<luacpp::LuaValue>(1);
if (testVal.getValueType() == luacpp::ValueType::NIL) {
// If there is no first array element then we assume it is an object
return tableToJsonObject(tableVal);
} else {
// Assume this is an object
return tableToJsonArray(tableVal);
}
}
json_t* LuaValueSerializer::tableToJsonArray(const luacpp::LuaTable& table)
{
auto size = table.getLength();
auto jsonArray = json_array();
for (size_t i = 1; i <= size; ++i) {
luacpp::LuaValue arrayVal;
if (!table.getValue(i, arrayVal)) {
json_array_append_new(jsonArray, json_null());
} else {
LuaValueSerializer valueSerializer(std::move(arrayVal));
json_array_append_new(jsonArray, valueSerializer.toJson());
}
}
return jsonArray;
}
json_t* LuaValueSerializer::tableToJsonObject(const luacpp::LuaTable& table)
{
auto jsonObj = json_object();
for (const auto& entry : table) {
if (entry.first.getValueType() != luacpp::ValueType::STRING) {
// Ignore non-string indices
continue;
}
const auto index = entry.first.getValue<SCP_string>();
LuaValueSerializer valueSerializer(entry.second);
json_object_set_new(jsonObj, index.c_str(), valueSerializer.toJson());
}
return jsonObj;
}
} // namespace util
} // namespace scripting