File: LuaValueSerializer.cpp

package info (click to toggle)
freespace2 24.0.2%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: trixie
  • size: 43,188 kB
  • sloc: cpp: 583,107; ansic: 21,729; python: 1,174; sh: 464; makefile: 248; xml: 181
file content (101 lines) | stat: -rw-r--r-- 2,885 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

#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(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