From d33edd4cd99280d9672f4bb0685035cffb146074 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 7 May 2024 16:00:52 +0300 Subject: [PATCH] 'dynamic' namespace refactor (step 1/2) --- src/assets/AssetsLoader.cpp | 6 +- src/coders/binary_json.cpp | 50 +++---- src/coders/json.cpp | 137 +++++++++--------- src/coders/json.hpp | 17 +-- src/constants.hpp | 4 +- src/data/dynamic.cpp | 203 +++++---------------------- src/data/dynamic.hpp | 72 +++++----- src/engine.cpp | 1 + src/files/settings_io.cpp | 45 +++--- src/frontend/locale.cpp | 6 +- src/items/Inventory.cpp | 8 +- src/logic/EngineController.cpp | 2 +- src/logic/scripting/lua/LuaState.cpp | 63 ++++----- src/logic/scripting/lua/libjson.cpp | 16 +-- src/objects/Player.cpp | 2 +- src/world/World.cpp | 8 +- 16 files changed, 248 insertions(+), 392 deletions(-) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 4fb972c6..ae71d032 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -116,7 +116,7 @@ void AssetsLoader::processPreload( switch (tag) { case AssetType::sound: add(tag, path, name, std::make_shared( - map->getBool("keep-pcm", false) + map->get("keep-pcm", false) )); break; default: @@ -131,13 +131,13 @@ void AssetsLoader::processPreloadList(AssetType tag, dynamic::List* list) { } for (uint i = 0; i < list->size(); i++) { auto value = list->get(i); - switch (value->type) { + switch (static_cast(value->value.index())) { case dynamic::valtype::string: processPreload(tag, std::get(value->value), nullptr); break; case dynamic::valtype::map: { auto map = std::get(value->value); - auto name = map->getStr("name"); + auto name = map->get("name"); processPreload(tag, name, map); break; } diff --git a/src/coders/binary_json.cpp b/src/coders/binary_json.cpp index c6e7f533..0ee7ab00 100644 --- a/src/coders/binary_json.cpp +++ b/src/coders/binary_json.cpp @@ -10,7 +10,7 @@ using namespace json; using namespace dynamic; static void to_binary(ByteBuilder& builder, const Value* value) { - switch (value->type) { + switch (static_cast(value->value.index())) { case valtype::none: throw std::runtime_error("none value is not implemented"); case valtype::map: { @@ -56,8 +56,8 @@ static void to_binary(ByteBuilder& builder, const Value* value) { } } -static List* array_from_binary(ByteReader& reader); -static Map* object_from_binary(ByteReader& reader); +static std::unique_ptr array_from_binary(ByteReader& reader); +static std::unique_ptr object_from_binary(ByteReader& reader); std::vector json::to_binary(const Map* obj, bool compress) { if (compress) { @@ -83,76 +83,66 @@ std::vector json::to_binary(const Map* obj, bool compress) { return builder.build(); } -static Value* value_from_binary(ByteReader& reader) { +static std::unique_ptr value_from_binary(ByteReader& reader) { ubyte typecode = reader.get(); - valtype type; valvalue val; switch (typecode) { case BJSON_TYPE_DOCUMENT: - type = valtype::map; reader.getInt32(); - val = object_from_binary(reader); + val = object_from_binary(reader).release(); break; case BJSON_TYPE_LIST: - type = valtype::list; - val = array_from_binary(reader); + val = array_from_binary(reader).release(); break; case BJSON_TYPE_BYTE: - type = valtype::integer; val = static_cast(reader.get()); break; case BJSON_TYPE_INT16: - type = valtype::integer; val = static_cast(reader.getInt16()); break; case BJSON_TYPE_INT32: - type = valtype::integer; val = static_cast(reader.getInt32()); break; case BJSON_TYPE_INT64: - type = valtype::integer; val = reader.getInt64(); break; case BJSON_TYPE_NUMBER: - type = valtype::number; val = reader.getFloat64(); break; case BJSON_TYPE_FALSE: case BJSON_TYPE_TRUE: - type = valtype::boolean; val = (typecode - BJSON_TYPE_FALSE) != 0; break; case BJSON_TYPE_STRING: - type = valtype::string; val = reader.getString(); break; default: throw std::runtime_error( - "type "+std::to_string(typecode)+" is not supported"); + "type "+std::to_string(typecode)+" is not supported" + ); } - return new Value(type, val); + return std::make_unique(val); } -static List* array_from_binary(ByteReader& reader) { +static std::unique_ptr array_from_binary(ByteReader& reader) { auto array = std::make_unique(); auto& items = array->values; while (reader.peek() != BJSON_END) { - items.push_back(std::unique_ptr(value_from_binary(reader))); + items.push_back(value_from_binary(reader)); } reader.get(); - return array.release(); + return array; } -static Map* object_from_binary(ByteReader& reader) { +static std::unique_ptr object_from_binary(ByteReader& reader) { auto obj = std::make_unique(); auto& map = obj->values; while (reader.peek() != BJSON_END) { const char* key = reader.getCString(); - Value* value = value_from_binary(reader); - map.insert(std::make_pair(key, value)); + map.insert(std::make_pair(key, value_from_binary(reader))); } reader.get(); - return obj.release(); + return obj; } std::unique_ptr json::from_binary(const ubyte* src, size_t size) { @@ -166,11 +156,13 @@ std::unique_ptr json::from_binary(const ubyte* src, size_t size) { } else { ByteReader reader(src, size); std::unique_ptr value (value_from_binary(reader)); - if (value->type != valtype::map) { + + if (Map* const* map = std::get_if(&value->value)) { + std::unique_ptr obj (*map); + value->value = (Map*)nullptr; + return obj; + } else { throw std::runtime_error("root value is not an object"); } - std::unique_ptr obj (std::get(value->value)); - value->value = (Map*)nullptr; - return obj; } } diff --git a/src/coders/json.cpp b/src/coders/json.cpp index 1bb64776..32b0b16e 100644 --- a/src/coders/json.cpp +++ b/src/coders/json.cpp @@ -11,9 +11,11 @@ using namespace json; using namespace dynamic; -inline void newline(std::stringstream& ss, - bool nice, uint indent, - const std::string& indentstr) { +inline void newline( + std::stringstream& ss, + bool nice, uint indent, + const std::string& indentstr +) { if (nice) { ss << "\n"; for (uint i = 0; i < indent; i++) { @@ -24,29 +26,34 @@ inline void newline(std::stringstream& ss, } } -void stringify(const Value* value, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice); +void stringify( + const Value* value, + std::stringstream& ss, + int indent, + const std::string& indentstr, + bool nice +); -void stringifyObj(const Map* obj, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice); +void stringifyObj( + const Map* obj, + std::stringstream& ss, + int indent, + const std::string& indentstr, + bool nice +); -void stringify(const Value* value, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice) { - if (value->type == valtype::map) { - auto map = std::get(value->value); - stringifyObj(map, ss, indent, indentstr, nice); +void stringify( + const Value* value, + std::stringstream& ss, + int indent, + const std::string& indentstr, + bool nice +) { + if (auto map = std::get_if(&value->value)) { + stringifyObj(*map, ss, indent, indentstr, nice); } - else if (value->type == valtype::list) { - auto list = std::get(value->value); + else if (auto listptr = std::get_if(&value->value)) { + auto list = *listptr; if (list->size() == 0) { ss << "[]"; return; @@ -66,23 +73,24 @@ void stringify(const Value* value, newline(ss, true, indent - 1, indentstr); } ss << ']'; - } else if (value->type == valtype::boolean) { - ss << (std::get(value->value) ? "true" : "false"); - } else if (value->type == valtype::number) { - ss << std::setprecision(15); - ss << std::get(value->value); - } else if (value->type == valtype::integer) { - ss << std::get(value->value); - } else if (value->type == valtype::string) { - ss << util::escape(std::get(value->value)); + } else if (auto flag = std::get_if(&value->value)) { + ss << (*flag ? "true" : "false"); + } else if (auto num = std::get_if(&value->value)) { + ss << std::setprecision(15) << *num; + } else if (auto num = std::get_if(&value->value)) { + ss << *num; + } else if (auto str = std::get_if(&value->value)) { + ss << util::escape(*str); } } -void stringifyObj(const Map* obj, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice) { +void stringifyObj( + const Map* obj, + std::stringstream& ss, + int indent, + const std::string& indentstr, + bool nice +) { if (obj->values.empty()) { ss << "{}"; return; @@ -109,9 +117,10 @@ void stringifyObj(const Map* obj, } std::string json::stringify( - const Map* obj, - bool nice, - const std::string& indent) { + const Map* obj, + bool nice, + const std::string& indent +) { std::stringstream ss; stringifyObj(obj, ss, 1, indent, nice); return ss.str(); @@ -121,7 +130,7 @@ Parser::Parser(const std::string& filename, const std::string& source) : BasicParser(filename, source) { } -Map* Parser::parse() { +std::unique_ptr Parser::parse() { char next = peek(); if (next != '{') { throw error("'{' expected"); @@ -129,7 +138,7 @@ Map* Parser::parse() { return parseObject(); } -Map* Parser::parseObject() { +std::unique_ptr Parser::parseObject() { expect('{'); auto obj = std::make_unique(); auto& map = obj->values; @@ -155,10 +164,10 @@ Map* Parser::parseObject() { } } pos++; - return obj.release(); + return obj; } -List* Parser::parseList() { +std::unique_ptr Parser::parseList() { expect('['); auto arr = std::make_unique(); auto& values = arr->values; @@ -167,7 +176,7 @@ List* Parser::parseList() { skipLine(); continue; } - values.push_back(std::unique_ptr(parseValue())); + values.push_back(parseValue()); char next = peek(); if (next == ',') { @@ -179,73 +188,63 @@ List* Parser::parseList() { } } pos++; - return arr.release(); + return arr; } -Value* Parser::parseValue() { +std::unique_ptr Parser::parseValue() { char next = peek(); dynamic::valvalue val; if (next == '-' || next == '+') { pos++; number_u num; - valtype type; if (parseNumber(next == '-' ? -1 : 1, num)) { val = std::get(num); - type = valtype::integer; } else { val = std::get(num); - type = valtype::number; } - return new Value(type, val); + return std::make_unique(val); } if (is_identifier_start(next)) { std::string literal = parseName(); if (literal == "true") { - val = true; - return new Value(valtype::boolean, val); + return Value::boolean(true); } else if (literal == "false") { - val = false; - return new Value(valtype::boolean, val); + return Value::boolean(false); } else if (literal == "inf") { - val = INFINITY; - return new Value(valtype::number, val); + return Value::of(INFINITY); } else if (literal == "nan") { - val = NAN; - return new Value(valtype::number, val); + return Value::of(NAN); } throw error("invalid literal "); } if (next == '{') { - val = parseObject(); - return new Value(valtype::map, val); + val = parseObject().release(); + return std::make_unique(val); } if (next == '[') { - val = parseList(); - return new Value(valtype::list, val); + val = parseList().release(); + return std::make_unique(val); } if (is_digit(next)) { number_u num; - valtype type; if (parseNumber(1, num)) { val = std::get(num); - type = valtype::integer; } else { val = std::get(num); - type = valtype::number; } - return new Value(type, val); + return std::make_unique(val); } if (next == '"' || next == '\'') { pos++; val = parseString(next); - return new Value(valtype::string, val); + return std::make_unique(val); } throw error("unexpected character '"+std::string({next})+"'"); } std::unique_ptr json::parse(const std::string& filename, const std::string& source) { Parser parser(filename, source); - return std::unique_ptr(parser.parse()); + return parser.parse(); } std::unique_ptr json::parse(const std::string& source) { diff --git a/src/coders/json.hpp b/src/coders/json.hpp index 95b3a942..5709d5a4 100644 --- a/src/coders/json.hpp +++ b/src/coders/json.hpp @@ -20,22 +20,23 @@ namespace dynamic { namespace json { class Parser : public BasicParser { - dynamic::List* parseList(); - dynamic::Map* parseObject(); - dynamic::Value* parseValue(); + std::unique_ptr parseList(); + std::unique_ptr parseObject(); + std::unique_ptr parseValue(); public: Parser(const std::string& filename, const std::string& source); - dynamic::Map* parse(); + std::unique_ptr parse(); }; - extern std::unique_ptr parse(const std::string& filename, const std::string& source); - extern std::unique_ptr parse(const std::string& source); + std::unique_ptr parse(const std::string& filename, const std::string& source); + std::unique_ptr parse(const std::string& source); - extern std::string stringify( + std::string stringify( const dynamic::Map* obj, bool nice, - const std::string& indent); + const std::string& indent + ); } #endif // CODERS_JSON_HPP_ diff --git a/src/constants.hpp b/src/constants.hpp index 202d7ac5..de6b23dc 100644 --- a/src/constants.hpp +++ b/src/constants.hpp @@ -17,8 +17,8 @@ inline constexpr bool ENGINE_DEBUG_BUILD = true; inline const std::string ENGINE_VERSION_STRING = "0.21"; -inline constexpr int BLOCK_AIR = 0; -inline constexpr int ITEM_EMPTY = 0; +inline constexpr blockid_t BLOCK_AIR = 0; +inline constexpr itemid_t ITEM_EMPTY = 0; inline constexpr int CHUNK_W = 16; inline constexpr int CHUNK_H = 256; diff --git a/src/data/dynamic.cpp b/src/data/dynamic.cpp index 89ed67ff..e9dc0c1c 100644 --- a/src/data/dynamic.cpp +++ b/src/data/dynamic.cpp @@ -1,7 +1,5 @@ #include "dynamic.hpp" -#include - using namespace dynamic; List::~List() { @@ -9,7 +7,7 @@ List::~List() { std::string List::str(size_t index) const { const auto& val = values[index]; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::string: return std::get(val->value); case valtype::boolean: return std::get(val->value) ? "true" : "false"; case valtype::number: return std::to_string(std::get(val->value)); @@ -21,7 +19,7 @@ std::string List::str(size_t index) const { number_t List::num(size_t index) const { const auto& val = values[index]; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::number: return std::get(val->value); case valtype::integer: return std::get(val->value); case valtype::string: return std::stoll(std::get(val->value)); @@ -33,7 +31,7 @@ number_t List::num(size_t index) const { integer_t List::integer(size_t index) const { const auto& val = values[index]; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::number: return std::get(val->value); case valtype::integer: return std::get(val->value); case valtype::string: return std::stoll(std::get(val->value)); @@ -44,22 +42,24 @@ integer_t List::integer(size_t index) const { } Map* List::map(size_t index) const { - if (values[index]->type != valtype::map) { + if (auto* val = std::get_if(&values[index]->value)) { + return *val; + } else { throw std::runtime_error("type error"); } - return std::get(values[index]->value); } List* List::list(size_t index) const { - if (values[index]->type != valtype::list) { + if (auto* val = std::get_if(&values[index]->value)) { + return *val; + } else { throw std::runtime_error("type error"); } - return std::get(values[index]->value); } bool List::flag(size_t index) const { const auto& val = values[index]; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::integer: return std::get(val->value); case valtype::boolean: return std::get(val->value); default: @@ -74,57 +74,11 @@ Value* List::getValueWriteable(size_t index) const { return values.at(index).get(); } -List& List::put(std::string value) { - values.push_back(std::make_unique(valtype::string, value)); - return *this; -} - -List& List::put(uint value) { - return put((int64_t)value); -} - -List& List::put(int value) { - return put((int64_t)value); -} - -List& List::put(int64_t value) { - values.push_back(std::make_unique(valtype::integer, value)); - return *this; -} - -List& List::put(uint64_t value) { - return put((int64_t)value); -} - -List& List::put(double value) { - values.push_back(std::make_unique(valtype::number, value)); - return *this; -} - -List& List::put(float value) { - return put((double)value); -} - -List& List::put(bool value) { - values.push_back(std::make_unique(valtype::boolean, value)); - return *this; -} - List& List::put(std::unique_ptr value) { values.emplace_back(std::move(value)); return *this; } -List& List::put(Map* value) { - values.push_back(std::make_unique(valtype::map, value)); - return *this; -} - -List& List::put(List* value) { - values.push_back(std::make_unique(valtype::list, value)); - return *this; -} - List& List::putList() { List* arr = new List(); put(arr); @@ -145,57 +99,29 @@ Map::~Map() { } void Map::str(std::string key, std::string& dst) const { - dst = getStr(key, dst); + dst = get(key, dst); } -std::string Map::getStr(std::string key) const { - if (values.find(key) == values.end()) { - throw std::runtime_error("missing key '"+key+"'"); - } - return getStr(key, ""); -} - -double Map::getNum(std::string key) const { - if (values.find(key) == values.end()) { - throw std::runtime_error("missing key '"+key+"'"); - } - return getNum(key, 0); -} - -int64_t Map::getInt(std::string key) const { - if (values.find(key) == values.end()) { - throw std::runtime_error("missing key '"+key+"'"); - } - return getInt(key, 0); -} - -bool Map::getBool(std::string key) const { - if (values.find(key) == values.end()) { - throw std::runtime_error("missing key '"+key+"'"); - } - return getBool(key, false); -} - -std::string Map::getStr(std::string key, const std::string& def) const { +std::string Map::get(const std::string& key, const std::string def) const { auto found = values.find(key); if (found == values.end()) return def; auto& val = found->second; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::string: return std::get(val->value); case valtype::boolean: return std::get(val->value) ? "true" : "false"; case valtype::number: return std::to_string(std::get(val->value)); case valtype::integer: return std::to_string(std::get(val->value)); default: throw std::runtime_error("type error"); - } + } } -number_t Map::getNum(std::string key, double def) const { +number_t Map::get(const std::string& key, double def) const { auto found = values.find(key); if (found == values.end()) return def; auto& val = found->second; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::number: return std::get(val->value); case valtype::integer: return std::get(val->value); case valtype::string: return std::stoull(std::get(val->value)); @@ -204,12 +130,12 @@ number_t Map::getNum(std::string key, double def) const { } } -integer_t Map::getInt(std::string key, integer_t def) const { +integer_t Map::get(const std::string& key, integer_t def) const { auto found = values.find(key); if (found == values.end()) return def; auto& val = found->second; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::number: return std::get(val->value); case valtype::integer: return std::get(val->value); case valtype::string: return std::stoull(std::get(val->value)); @@ -218,12 +144,12 @@ integer_t Map::getInt(std::string key, integer_t def) const { } } -bool Map::getBool(std::string key, bool def) const { +bool Map::get(const std::string& key, bool def) const { auto found = values.find(key); if (found == values.end()) return def; auto& val = found->second; - switch (val->type) { + switch (static_cast(val->value.index())) { case valtype::integer: return std::get(val->value); case valtype::boolean: return std::get(val->value); default: throw std::runtime_error("type error"); @@ -231,40 +157,39 @@ bool Map::getBool(std::string key, bool def) const { } void Map::num(std::string key, double& dst) const { - dst = getNum(key, dst); + dst = get(key, dst); } void Map::num(std::string key, float& dst) const { - dst = getNum(key, dst); + dst = get(key, static_cast(dst)); } void Map::num(std::string key, ubyte& dst) const { - dst = getInt(key, dst); + dst = get(key, static_cast(dst)); } void Map::num(std::string key, int& dst) const { - dst = getInt(key, dst); + dst = get(key, static_cast(dst)); } void Map::num(std::string key, int64_t& dst) const { - dst = getInt(key, dst); + dst = get(key, dst); } void Map::num(std::string key, uint64_t& dst) const { - dst = getInt(key, dst); + dst = get(key, static_cast(dst)); } void Map::num(std::string key, uint& dst) const { - dst = getInt(key, dst); + dst = get(key, static_cast(dst)); } Map* Map::map(std::string key) const { auto found = values.find(key); if (found != values.end()) { - auto& val = found->second; - if (val->type != valtype::map) - return nullptr; - return std::get(val->value); + if (auto* val = std::get_if(&found->second->value)) { + return *val; + } } return nullptr; } @@ -277,57 +202,7 @@ List* Map::list(std::string key) const { } void Map::flag(std::string key, bool& dst) const { - dst = getBool(key, dst); -} - -Map& Map::put(std::string key, uint value) { - return put(key, (int64_t)value); -} - -Map& Map::put(std::string key, int value) { - return put(key, (int64_t)value); -} - -Map& Map::put(std::string key, int64_t value) { - values[key] = std::make_unique(valtype::integer, value); - return *this; -} - -Map& Map::put(std::string key, uint64_t value) { - return put(key, (int64_t)value); -} - -Map& Map::put(std::string key, float value) { - return put(key, (double)value); -} - -Map& Map::put(std::string key, double value) { - values[key] = std::make_unique(valtype::number, value); - return *this; -} - -Map& Map::put(std::string key, std::string value){ - values[key] = std::make_unique(valtype::string, value); - return *this; -} - -Map& Map::put(std::string key, const char* value) { - return put(key, std::string(value)); -} - -Map& Map::put(std::string key, Map* value){ - values[key] = std::make_unique(valtype::map, value); - return *this; -} - -Map& Map::put(std::string key, List* value){ - values[key] = std::make_unique(valtype::list, value); - return *this; -} - -Map& Map::put(std::string key, bool value){ - values[key] = std::make_unique(valtype::boolean, value); - return *this; + dst = get(key, dst); } Map& Map::put(std::string key, std::unique_ptr value) { @@ -351,7 +226,7 @@ Map& Map::putMap(std::string key) { return *obj; } -bool Map::has(std::string key) { +bool Map::has(const std::string& key) const { return values.find(key) != values.end(); } @@ -359,11 +234,11 @@ size_t Map::size() const { return values.size(); } -Value::Value(valtype type, valvalue value) : type(type), value(value) { +Value::Value(valvalue value) : value(value) { } Value::~Value() { - switch (type) { + switch (static_cast(value.index())) { case valtype::map: delete std::get(value); break; case valtype::list: delete std::get(value); break; default: @@ -372,21 +247,21 @@ Value::~Value() { } std::unique_ptr Value::boolean(bool value) { - return std::make_unique(valtype::boolean, value); + return std::make_unique(value); } std::unique_ptr Value::of(number_u value) { if (std::holds_alternative(value)) { - return std::make_unique(valtype::integer, std::get(value)); + return std::make_unique(std::get(value)); } else { - return std::make_unique(valtype::number, std::get(value)); + return std::make_unique(std::get(value)); } } std::unique_ptr Value::of(const std::string& value) { - return std::make_unique(valtype::string, value); + return std::make_unique(value); } std::unique_ptr Value::of(std::unique_ptr value) { - return std::make_unique(valtype::map, value.release()); + return std::make_unique(value.release()); } diff --git a/src/data/dynamic.hpp b/src/data/dynamic.hpp index 7e9ef327..e35a54f6 100644 --- a/src/data/dynamic.hpp +++ b/src/data/dynamic.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace dynamic { @@ -15,10 +16,11 @@ namespace dynamic { class Value; enum class valtype { - none, map, list, number, integer, string, boolean + none=0, map, list, string, number, boolean, integer }; using valvalue = std::variant< + std::monostate, Map*, List*, std::string, @@ -29,9 +31,8 @@ namespace dynamic { class Value { public: - valtype type; valvalue value; - Value(valtype type, valvalue value); + Value(valvalue value); ~Value(); static std::unique_ptr boolean(bool value); @@ -60,16 +61,11 @@ namespace dynamic { return values.at(i).get(); } - List& put(uint value); - List& put(int value); - List& put(uint64_t value); - List& put(int64_t value); - List& put(float value); - List& put(double value); - List& put(std::string value); - List& put(Map* value); - List& put(List* value); - List& put(bool value); + template + List& put(T value) { + return put(std::make_unique(value)); + } + List& put(std::unique_ptr value); Value* getValueWriteable(size_t index) const; @@ -85,15 +81,28 @@ namespace dynamic { std::unordered_map> values; ~Map(); - std::string getStr(std::string key) const; - number_t getNum(std::string key) const; - integer_t getInt(std::string key) const; - bool getBool(std::string key) const; + template + T get(const std::string& key) const { + if (!has(key)) { + throw std::runtime_error("missing key '"+key+"'"); + } + return get(key, T()); + } - std::string getStr(std::string key, const std::string& def) const; - number_t getNum(std::string key, double def) const; - integer_t getInt(std::string key, integer_t def) const; - bool getBool(std::string key, bool def) const; + std::string get(const std::string& key, const std::string def) const; + number_t get(const std::string& key, double def) const; + integer_t get(const std::string& key, integer_t def) const; + bool get(const std::string& key, bool def) const; + + int get(const std::string& key, int def) const { + return get(key, static_cast(def)); + } + uint get(const std::string& key, uint def) const { + return get(key, static_cast(def)); + } + uint64_t get(const std::string& key, uint64_t def) const { + return get(key, static_cast(def)); + } void str(std::string key, std::string& dst) const; void num(std::string key, int& dst) const; @@ -107,17 +116,14 @@ namespace dynamic { List* list(std::string key) const; void flag(std::string key, bool& dst) const; - Map& put(std::string key, uint value); - Map& put(std::string key, int value); - Map& put(std::string key, int64_t value); - Map& put(std::string key, uint64_t value); - Map& put(std::string key, float value); - Map& put(std::string key, double value); - Map& put(std::string key, const char* value); - Map& put(std::string key, std::string value); - Map& put(std::string key, Map* value); - Map& put(std::string key, List* value); - Map& put(std::string key, bool value); + template + Map& put(std::string key, T value) { + return put(key, std::make_unique(value)); + } + Map& put(std::string key, uint64_t value) { + return put(key, Value::of(static_cast(value))); + } + Map& put(std::string key, std::unique_ptr value); void remove(const std::string& key); @@ -125,7 +131,7 @@ namespace dynamic { List& putList(std::string key); Map& putMap(std::string key); - bool has(std::string key); + bool has(const std::string& key) const; size_t size() const; }; } diff --git a/src/engine.cpp b/src/engine.cpp index 2f38e9b0..17c5d976 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -185,6 +185,7 @@ void Engine::processPostRunnables() { void Engine::saveSettings() { logger.info() << "saving settings"; files::write_string(paths->getSettingsFile(), toml::stringify(settingsHandler)); + logger.info() << "saving bindings"; files::write_string(paths->getControlsFile(), Events::writeBindings()); } diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index 2769c8fd..87a705a8 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -119,18 +119,14 @@ bool SettingsHandler::has(const std::string& name) const { template static void set_numeric_value(T* setting, const dynamic::Value& value) { - switch (value.type) { - case dynamic::valtype::integer: - setting->set(std::get(value.value)); - break; - case dynamic::valtype::number: - setting->set(std::get(value.value)); - break; - case dynamic::valtype::boolean: - setting->set(std::get(value.value)); - break; - default: - throw std::runtime_error("type error, numeric value expected"); + if (auto num = std::get_if(&value.value)) { + setting->set(*num); + } else if (auto num = std::get_if(&value.value)) { + setting->set(*num); + } else if (auto flag = std::get_if(&value.value)) { + setting->set(*flag); + } else { + throw std::runtime_error("type error, numeric value expected"); } } @@ -147,21 +143,16 @@ void SettingsHandler::setValue(const std::string& name, const dynamic::Value& va } else if (auto flag = dynamic_cast(setting)) { set_numeric_value(flag, value); } else if (auto string = dynamic_cast(setting)) { - switch (value.type) { - case dynamic::valtype::string: - string->set(std::get(value.value)); - break; - case dynamic::valtype::integer: - string->set(std::to_string(std::get(value.value))); - break; - case dynamic::valtype::number: - string->set(std::to_string(std::get(value.value))); - break; - case dynamic::valtype::boolean: - string->set(std::to_string(std::get(value.value))); - break; - default: - throw std::runtime_error("not implemented for type"); + if (auto num = std::get_if(&value.value)) { + string->set(std::to_string(*num)); + } else if (auto num = std::get_if(&value.value)) { + string->set(std::to_string(*num)); + } else if (auto flag = std::get_if(&value.value)) { + string->set(*flag ? "true" : "false"); + } else if (auto str = std::get_if(&value.value)) { + string->set(*str); + } else { + throw std::runtime_error("not implemented for type"); } } else { throw std::runtime_error("type is not implement - setting '"+name+"'"); diff --git a/src/frontend/locale.cpp b/src/frontend/locale.cpp index caeaedd6..f99e5fd3 100644 --- a/src/frontend/locale.cpp +++ b/src/frontend/locale.cpp @@ -11,6 +11,7 @@ static debug::Logger logger("locale"); namespace fs = std::filesystem; +using namespace std::literals; std::unique_ptr langs::current; std::unordered_map langs::locales_info; @@ -78,12 +79,11 @@ void langs::loadLocalesInfo(const fs::path& resdir, std::string& fallback) { auto langInfo = entry.second.get(); std::string name; - if (langInfo->type == dynamic::valtype::map) { - name = std::get(langInfo->value)->getStr("name", "none"); + if (auto mapptr = std::get_if(&langInfo->value)) { + name = (*mapptr)->get("name", "none"s); } else { continue; } - std::cout << "[" << entry.first << " (" << name << ")] "; langs::locales_info[entry.first] = LocaleInfo {entry.first, name}; } diff --git a/src/items/Inventory.cpp b/src/items/Inventory.cpp index a21de911..c8ce5aac 100644 --- a/src/items/Inventory.cpp +++ b/src/items/Inventory.cpp @@ -50,7 +50,7 @@ void Inventory::move( } void Inventory::deserialize(dynamic::Map* src) { - id = src->getNum("id", 1); + id = src->get("id", 1); auto slotsarr = src->list("slots"); size_t slotscount = slotsarr->size(); while (slots.size() < slotscount) { @@ -58,8 +58,8 @@ void Inventory::deserialize(dynamic::Map* src) { } for (size_t i = 0; i < slotscount; i++) { auto item = slotsarr->map(i); - itemid_t id = item->getInt("id", ITEM_EMPTY); - itemcount_t count = item->getInt("count", 0); + itemid_t id = item->get("id", ITEM_EMPTY); + itemcount_t count = item->get("count", 0); auto& slot = slots[i]; slot.set(ItemStack(id, count)); } @@ -88,7 +88,7 @@ void Inventory::convert(dynamic::Map* data, const ContentLUT* lut) { auto slotsarr = data->list("slots"); for (size_t i = 0; i < slotsarr->size(); i++) { auto item = slotsarr->map(i); - itemid_t id = item->getInt("id", ITEM_EMPTY); + itemid_t id = item->get("id", ITEM_EMPTY); itemid_t replacement = lut->getItemId(id); item->put("id", replacement); if (replacement == 0 && item->has("count")) { diff --git a/src/logic/EngineController.cpp b/src/logic/EngineController.cpp index 13399d35..82956279 100644 --- a/src/logic/EngineController.cpp +++ b/src/logic/EngineController.cpp @@ -81,7 +81,7 @@ static void show_content_missing( contentEntry.put("name", entry.name); } std::vector> args; - args.emplace_back(std::make_unique(valtype::map, root.release())); + args.emplace_back(std::make_unique(root.release())); menus::show(engine, "reports/missing_content", std::move(args)); } diff --git a/src/logic/scripting/lua/LuaState.cpp b/src/logic/scripting/lua/LuaState.cpp index 4d44e33c..717f96e6 100644 --- a/src/logic/scripting/lua/LuaState.cpp +++ b/src/logic/scripting/lua/LuaState.cpp @@ -217,41 +217,32 @@ int lua::LuaState::pushvalue(int idx) { } int lua::LuaState::pushvalue(const dynamic::Value& value) { - using dynamic::valtype; - switch (value.type) { - case valtype::boolean: - pushboolean(std::get(value.value)); - break; - case valtype::integer: - pushinteger(std::get(value.value)); - break; - case valtype::number: - pushnumber(std::get(value.value)); - break; - case valtype::string: - pushstring(std::get(value.value).c_str()); - break; - case valtype::none: - pushnil(); - break; - case valtype::list: { - auto list = std::get(value.value); - lua_createtable(L, list->size(), 0); - for (size_t i = 0; i < list->size(); i++) { - pushvalue(*list->get(i)); - lua_rawseti(L, -2, i+1); - } - break; + using namespace dynamic; + + if (auto* flag = std::get_if(&value.value)) { + pushboolean(*flag); + } else if (auto* num = std::get_if(&value.value)) { + pushinteger(*num); + } else if (auto* num = std::get_if(&value.value)) { + pushnumber(*num); + } else if (auto* str = std::get_if(&value.value)) { + pushstring(str->c_str()); + } else if (List* const* listptr = std::get_if(&value.value)) { + auto list = *listptr; + lua_createtable(L, list->size(), 0); + for (size_t i = 0; i < list->size(); i++) { + pushvalue(*list->get(i)); + lua_rawseti(L, -2, i+1); } - case valtype::map: { - auto map = std::get(value.value); - lua_createtable(L, 0, map->size()); - for (auto& entry : map->values) { - pushvalue(*entry.second); - lua_setfield(L, -2, entry.first.c_str()); - } - break; + } else if (Map* const* mapptr = std::get_if(&value.value)) { + auto map = *mapptr; + lua_createtable(L, 0, map->size()); + for (auto& entry : map->values) { + pushvalue(*entry.second); + lua_setfield(L, -2, entry.first.c_str()); } + } else { + pushnil(); } return 1; } @@ -318,7 +309,7 @@ std::unique_ptr lua::LuaState::tovalue(int idx) { switch (type) { case LUA_TNIL: case LUA_TNONE: - return std::make_unique(valtype::none, (integer_t)0); + return std::make_unique(std::monostate()); case LUA_TBOOLEAN: return Value::boolean(lua_toboolean(L, idx) == 1); case LUA_TNUMBER: { @@ -342,7 +333,7 @@ std::unique_ptr lua::LuaState::tovalue(int idx) { list->put(tovalue(-1)); lua_pop(L, 1); } - return std::make_unique(valtype::list, list.release()); + return std::make_unique(list.release()); } else { // table auto map = std::make_unique(); @@ -355,7 +346,7 @@ std::unique_ptr lua::LuaState::tovalue(int idx) { lua_pop(L, 2); } lua_pop(L, 1); - return std::make_unique(valtype::map, map.release()); + return std::make_unique(map.release()); } } default: diff --git a/src/logic/scripting/lua/libjson.cpp b/src/logic/scripting/lua/libjson.cpp index 9dc71bca..542be7cf 100644 --- a/src/logic/scripting/lua/libjson.cpp +++ b/src/logic/scripting/lua/libjson.cpp @@ -11,22 +11,22 @@ namespace scripting { static int l_json_stringify(lua_State* L) { auto value = scripting::state->tovalue(1); - if (value->type != dynamic::valtype::map) { + + if (auto mapptr = std::get_if(&value->value)) { + bool nice = lua_toboolean(L, 2); + auto string = json::stringify(*mapptr, nice, " "); + lua_pushstring(L, string.c_str()); + return 1; + } else { luaL_error(L, "table expected"); return 0; } - bool nice = lua_toboolean(L, 2); - auto string = json::stringify(std::get(value->value), nice, " "); - lua_pushstring(L, string.c_str()); - return 1; } static int l_json_parse(lua_State* L) { auto string = lua_tostring(L, 1); auto element = json::parse("", string); - auto value = std::make_unique( - dynamic::valtype::map, element.release() - ); + auto value = std::make_unique(element.release()); scripting::state->pushvalue(*value); return 1; } diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 4fd682af..7a85c722 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -227,7 +227,7 @@ void Player::deserialize(dynamic::Map *src) { src->flag("flight", flight); src->flag("noclip", noclip); - setChosenSlot(src->getInt("chosen-slot", getChosenSlot())); + setChosenSlot(src->get("chosen-slot", getChosenSlot())); auto invmap = src->map("inventory"); if (invmap) { diff --git a/src/world/World.cpp b/src/world/World.cpp index d774fc33..0d023d1d 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -174,9 +174,9 @@ const std::vector& World::getPacks() const { } void World::deserialize(dynamic::Map* root) { - name = root->getStr("name", name); - generator = root->getStr("generator", generator); - seed = root->getInt("seed", seed); + name = root->get("name", name); + generator = root->get("generator", generator); + seed = root->get("seed", seed); if(generator == "") { generator = WorldGenerators::getDefaultGeneratorID(); @@ -197,7 +197,7 @@ void World::deserialize(dynamic::Map* root) { timeobj->num("total-time", totalTime); } - nextInventoryId = root->getNum("next-inventory-id", 2); + nextInventoryId = root->get("next-inventory-id", 2); } std::unique_ptr World::serialize() const {