From 9ac42a48e5747ac5bb97c21df717eb7d1290fecc Mon Sep 17 00:00:00 2001 From: amasson Date: Fri, 1 Nov 2024 23:52:54 +0100 Subject: [PATCH 01/10] remove pointer usage from json #67 --- .../Scene/Assets/AssetResource_AssimpLoad.cpp | 53 ++++--- Engine/Utils/include/Utils/Json.hpp | 30 ++-- Engine/Utils/src/Utils/Json.cpp | 84 +++++----- Engine/Utils/test/test_Json.cpp | 150 +++++++++--------- 4 files changed, 168 insertions(+), 149 deletions(-) diff --git a/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp b/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp index 4538829..77f524d 100644 --- a/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp +++ b/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp @@ -236,69 +236,81 @@ void loadMaterials(AssetResource &assetResource, const aiScene *scene) { } } -std::shared_ptr loadMetadataEntry(const aiMetadataEntry &entry) { +void loadMetadataEntry(const aiMetadataEntry &entry, Json::Value &out) { switch (entry.mType) { case AI_BOOL: { const bool data = *static_cast(entry.mData); - return Json::boolean(data); + out.value = data; + return; } case AI_INT32: { const double data = *static_cast(entry.mData); - return Json::number(data); + out.value = data; + return; } case AI_UINT64: { const double data = *static_cast(entry.mData); - return Json::number(data); + out.value = data; + return; } case AI_FLOAT: { const double data = *static_cast(entry.mData); - return Json::number(data); + out.value = data; + return; } case AI_DOUBLE: { const double data = *static_cast(entry.mData); - return Json::number(data); + out.value = data; + return; } case AI_AIVECTOR3D: { + out.value = Json::Array(); + Json::Array &array(std::get(out.value)); const aiVector3D *data = static_cast(entry.mData); - Json::Array array_data; - array_data.push_back(Json::number(data->x)); - array_data.push_back(Json::number(data->y)); - array_data.push_back(Json::number(data->z)); - return Json::array(array_data); + array.push_back(Json::Value(data->x)); + array.push_back(Json::Value(data->y)); + array.push_back(Json::Value(data->z)); + return; } case AI_AIMETADATA: { + out.value = Json::Object(); + Json::Object &object(std::get(out.value)); const aiMetadata *data = static_cast(entry.mData); - Json::Object object_data; for (unsigned int i = 0; i < data->mNumProperties; ++i) { const aiString &key(data->mKeys[i]); const aiMetadataEntry &value(data->mValues[i]); - object_data[key.C_Str()] = loadMetadataEntry(value); + assert(key.C_Str() != nullptr); + loadMetadataEntry(value, object[key.C_Str()]); } - return Json::object(object_data); } case AI_INT64: { const double data = *static_cast(entry.mData); - return Json::number(data); + out.value = data; + return; } case AI_UINT32: { const double data = *static_cast(entry.mData); - return Json::number(data); + out.value = data; + return; + } + default: + { + out = Json::Value(); + return; } - default: break; } - return Json::null(); } -void loadMetadata(const aiMetadata *metadata, Json::Object &dst) { +void loadMetadata(const aiMetadata *metadata, Json::Object &out) { if (metadata == nullptr) return; @@ -306,7 +318,8 @@ void loadMetadata(const aiMetadata *metadata, Json::Object &dst) { const aiString &key(metadata->mKeys[i]); const aiMetadataEntry &value(metadata->mValues[i]); - dst[key.C_Str()] = loadMetadataEntry(value); + assert(key.C_Str() != nullptr); + loadMetadataEntry(value, out[key.C_Str()]); } } diff --git a/Engine/Utils/include/Utils/Json.hpp b/Engine/Utils/include/Utils/Json.hpp index 6271696..e1f8b6b 100644 --- a/Engine/Utils/include/Utils/Json.hpp +++ b/Engine/Utils/include/Utils/Json.hpp @@ -13,8 +13,8 @@ namespace Stone::Json { struct Value; -using Object = std::unordered_map>; -using Array = std::vector>; +using Object = std::unordered_map; +using Array = std::vector; struct Value { @@ -46,17 +46,17 @@ struct Value { return std::get(value); } - static std::shared_ptr parseString(const std::string &input); - static std::shared_ptr parseFile(const std::string &path); + static Value parseString(const std::string &input); + static Value parseFile(const std::string &path); std::string serialize() const; }; -std::shared_ptr object(const Object &obj = {}); -std::shared_ptr array(const Array &arr = {}); -std::shared_ptr string(const std::string &str = ""); -std::shared_ptr number(double num = 0.0); -std::shared_ptr boolean(bool b = false); -std::shared_ptr null(); +Value object(const Object &obj = {}); +Value array(const Array &arr = {}); +Value string(const std::string &str = ""); +Value number(double num = 0.0); +Value boolean(bool b = false); +Value null(); enum class TokenType { @@ -98,16 +98,16 @@ class Parser { public: explicit Parser(const std::string &input); - std::shared_ptr parse(); + void parse(Value &out); private: Lexer _lexer; Token _currentToken; - std::shared_ptr _parseValue(); - std::shared_ptr _parseObject(); - std::shared_ptr _parseArray(); - std::shared_ptr _parsePrimitive(); + void _parseValue(Value &out); + void _parseObject(Value &out); + void _parseArray(Value &out); + void _parsePrimitive(Value &out); void _consume(TokenType expected); }; diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index 5cf5874..7a732d1 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -28,12 +28,14 @@ Value::Value(bool b) : value(b) { Value::Value(std::nullptr_t n) : value(n) { } -std::shared_ptr Value::parseString(const std::string &input) { +Value Value::parseString(const std::string &input) { + Value ret; Parser parser(input); - return parser.parse(); + parser.parse(ret); + return ret; } -std::shared_ptr Value::parseFile(const std::string &path) { +Value Value::parseFile(const std::string &path) { return parseString(Utils::readTextFile(path)); } @@ -42,23 +44,28 @@ std::string Value::serialize() const { return serializer.serialize(*this); } -std::shared_ptr object(const Object &obj) { - return std::make_shared(obj); +Value object(const Object &obj) { + return Value(obj); } -std::shared_ptr array(const Array &arr) { - return std::make_shared(arr); + +Value array(const Array &arr) { + return Value(arr); } -std::shared_ptr string(const std::string &str) { - return std::make_shared(str); + +Value string(const std::string &str) { + return Value(str); } -std::shared_ptr number(double num) { - return std::make_shared(num); + +Value number(double num) { + return Value(num); } -std::shared_ptr boolean(bool b) { - return std::make_shared(b); + +Value boolean(bool b) { + return Value(b); } -std::shared_ptr null() { - return std::make_shared(); + +Value null() { + return Value(); } @@ -136,31 +143,32 @@ Parser::Parser(const std::string &input) : _lexer(input) { _currentToken = _lexer.nextToken(); } -std::shared_ptr Parser::parse() { - return _parseValue(); +void Parser::parse(Value &out) { + return _parseValue(out); } -std::shared_ptr Parser::_parseValue() { +void Parser::_parseValue(Value &out) { switch (_currentToken.type) { - case TokenType::LeftBrace: return _parseObject(); - case TokenType::LeftBracket: return _parseArray(); + case TokenType::LeftBrace: return _parseObject(out); + case TokenType::LeftBracket: return _parseArray(out); case TokenType::String: case TokenType::Number: case TokenType::True: case TokenType::False: - case TokenType::Null: return _parsePrimitive(); + case TokenType::Null: return _parsePrimitive(out); default: throw std::runtime_error("Unexpected token in input"); } } -std::shared_ptr Parser::_parseObject() { - Object object; +void Parser::_parseObject(Value &out) { + out.value = Object(); + Object &object(std::get(out.value)); _consume(TokenType::LeftBrace); while (_currentToken.type != TokenType::RightBrace) { std::string key = _currentToken.value; _consume(TokenType::String); _consume(TokenType::Colon); - object[key] = _parseValue(); + _parseValue(object[key]); if (_currentToken.type == TokenType::Comma) { _consume(TokenType::Comma); } else { @@ -168,14 +176,15 @@ std::shared_ptr Parser::_parseObject() { } } _consume(TokenType::RightBrace); - return std::make_shared(object); } -std::shared_ptr Parser::_parseArray() { - Array array; +void Parser::_parseArray(Value &out) { + out.value = Array(); + Array &array(std::get(out.value)); _consume(TokenType::LeftBracket); while (_currentToken.type != TokenType::RightBracket) { - array.push_back(_parseValue()); + array.push_back(Value()); + _parseValue(array.back()); if (_currentToken.type == TokenType::Comma) { _consume(TokenType::Comma); } else { @@ -183,21 +192,18 @@ std::shared_ptr Parser::_parseArray() { } } _consume(TokenType::RightBracket); - return std::make_shared(array); } -std::shared_ptr Parser::_parsePrimitive() { - std::shared_ptr value; +void Parser::_parsePrimitive(Value &out) { switch (_currentToken.type) { - case TokenType::String: value = std::make_shared(_currentToken.value); break; - case TokenType::Number: value = std::make_shared(std::stod(_currentToken.value)); break; - case TokenType::True: value = std::make_shared(true); break; - case TokenType::False: value = std::make_shared(false); break; - case TokenType::Null: value = std::make_shared(); break; + case TokenType::String: out.value = _currentToken.value; break; + case TokenType::Number: out.value = std::stod(_currentToken.value); break; + case TokenType::True: out.value = true; break; + case TokenType::False: out.value = false; break; + case TokenType::Null: out.value = std::nullptr_t(); break; default: throw std::runtime_error("Unexpected token in input"); } _currentToken = _lexer.nextToken(); - return value; } void Parser::_consume(TokenType expected) { @@ -220,7 +226,7 @@ void Serializer::operator()(const Object &object) { if (!first) _ss << ","; _ss << "\"" << pair.first << "\":"; - std::visit(*this, pair.second->value); + std::visit(*this, pair.second.value); first = false; } _ss << "}"; @@ -232,7 +238,7 @@ void Serializer::operator()(const Array &array) { for (const auto &item : array) { if (!first) _ss << ","; - std::visit(*this, item->value); + std::visit(*this, item.value); first = false; } _ss << "]"; diff --git a/Engine/Utils/test/test_Json.cpp b/Engine/Utils/test/test_Json.cpp index 7ddbe87..846c1d8 100644 --- a/Engine/Utils/test/test_Json.cpp +++ b/Engine/Utils/test/test_Json.cpp @@ -9,8 +9,8 @@ TEST(Json, ParseEmptyObject) { auto json = Json::Value::parseString(jsonString); - ASSERT_TRUE(json->is()); - ASSERT_TRUE(json->get().empty()); + ASSERT_TRUE(json.is()); + ASSERT_TRUE(json.get().empty()); } TEST(Json, ParseSimpleObject) { @@ -18,17 +18,17 @@ TEST(Json, ParseSimpleObject) { auto json = Json::Value::parseString(jsonString); - ASSERT_TRUE(json->is()); + ASSERT_TRUE(json.is()); - Json::Object obj = json->get(); - ASSERT_TRUE(obj["name"]->is()); - ASSERT_EQ(obj["name"]->get(), "John"); + Json::Object obj = json.get(); + ASSERT_TRUE(obj["name"].is()); + ASSERT_EQ(obj["name"].get(), "John"); - ASSERT_TRUE(obj["age"]->is()); - ASSERT_EQ(obj["age"]->get(), 30); + ASSERT_TRUE(obj["age"].is()); + ASSERT_EQ(obj["age"].get(), 30); - ASSERT_TRUE(obj["isStudent"]->is()); - ASSERT_EQ(obj["isStudent"]->get(), false); + ASSERT_TRUE(obj["isStudent"].is()); + ASSERT_EQ(obj["isStudent"].get(), false); } TEST(Json, ParseArray) { @@ -36,21 +36,21 @@ TEST(Json, ParseArray) { auto json = Json::Value::parseString(jsonString); - ASSERT_TRUE(json->is()); + ASSERT_TRUE(json.is()); - Json::Array arr = json->get(); + Json::Array arr = json.get(); ASSERT_EQ(arr.size(), 4); - ASSERT_TRUE(arr[0]->is()); - ASSERT_EQ(arr[0]->get(), 1); + ASSERT_TRUE(arr[0].is()); + ASSERT_EQ(arr[0].get(), 1); - ASSERT_TRUE(arr[1]->is()); - ASSERT_EQ(arr[1]->get(), "two"); + ASSERT_TRUE(arr[1].is()); + ASSERT_EQ(arr[1].get(), "two"); - ASSERT_TRUE(arr[2]->is()); - ASSERT_EQ(arr[2]->get(), true); + ASSERT_TRUE(arr[2].is()); + ASSERT_EQ(arr[2].get(), true); - ASSERT_TRUE(arr[3]->isNull()); + ASSERT_TRUE(arr[3].isNull()); } TEST(Json, ParseNestedObject) { @@ -58,17 +58,17 @@ TEST(Json, ParseNestedObject) { auto json = Json::Value::parseString(jsonString); - ASSERT_TRUE(json->is()); + ASSERT_TRUE(json.is()); - Json::Object obj = json->get(); - ASSERT_TRUE(obj["person"]->is()); + Json::Object obj = json.get(); + ASSERT_TRUE(obj["person"].is()); - Json::Object personObj = obj["person"]->get(); - ASSERT_TRUE(personObj["name"]->is()); - ASSERT_EQ(personObj["name"]->get(), "John"); + Json::Object personObj = obj["person"].get(); + ASSERT_TRUE(personObj["name"].is()); + ASSERT_EQ(personObj["name"].get(), "John"); - ASSERT_TRUE(personObj["age"]->is()); - ASSERT_EQ(personObj["age"]->get(), 30); + ASSERT_TRUE(personObj["age"].is()); + ASSERT_EQ(personObj["age"].get(), 30); } TEST(Json, MalformedJsonThrowsException) { @@ -92,7 +92,7 @@ TEST(JsonSerializer, SerializeEmptyObject) { Json::Object obj; auto value = Json::object(obj); - std::string result = value->serialize(); + std::string result = value.serialize(); ASSERT_EQ(result, "{}"); } @@ -108,23 +108,23 @@ TEST(JsonSerializer, SerializeSimpleObject) { auto value = Json::object(obj); - result = value->serialize(); + result = value.serialize(); } auto json = Json::Value::parseString(result); - ASSERT_TRUE(json->is()); + ASSERT_TRUE(json.is()); - auto obj = json->get(); + auto obj = json.get(); - ASSERT_TRUE(obj["name"]->is()); - ASSERT_EQ(obj["name"]->get(), "John"); + ASSERT_TRUE(obj["name"].is()); + ASSERT_EQ(obj["name"].get(), "John"); - ASSERT_TRUE(obj["age"]->is()); - ASSERT_EQ(obj["age"]->get(), 30); + ASSERT_TRUE(obj["age"].is()); + ASSERT_EQ(obj["age"].get(), 30); - ASSERT_TRUE(obj["isStudent"]->is()); - ASSERT_EQ(obj["isStudent"]->get(), false); + ASSERT_TRUE(obj["isStudent"].is()); + ASSERT_EQ(obj["isStudent"].get(), false); } TEST(JsonSerializer, SerializeArray) { @@ -134,26 +134,26 @@ TEST(JsonSerializer, SerializeArray) { { auto value = Json::array({Json::number(1.0), Json::string("two"), Json::boolean(true), Json::null()}); - result = value->serialize(); + result = value.serialize(); } auto json = Json::Value::parseString(result); - ASSERT_TRUE(json->is()); + ASSERT_TRUE(json.is()); - auto obj = json->get(); + auto obj = json.get(); ASSERT_EQ(obj.size(), 4); - ASSERT_TRUE(obj[0]->is()); - ASSERT_EQ(obj[0]->get(), 1); + ASSERT_TRUE(obj[0].is()); + ASSERT_EQ(obj[0].get(), 1); - ASSERT_TRUE(obj[1]->is()); - ASSERT_EQ(obj[1]->get(), "two"); + ASSERT_TRUE(obj[1].is()); + ASSERT_EQ(obj[1].get(), "two"); - ASSERT_TRUE(obj[2]->is()); - ASSERT_EQ(obj[2]->get(), true); + ASSERT_TRUE(obj[2].is()); + ASSERT_EQ(obj[2].get(), true); - ASSERT_TRUE(obj[3]->isNull()); + ASSERT_TRUE(obj[3].isNull()); } TEST(JsonSerializer, SerializeNestedObject) { @@ -165,24 +165,24 @@ TEST(JsonSerializer, SerializeNestedObject) { {"person", Json::object({{"name", Json::string("John")}, {"age", Json::number(30.0)}})} }); - result = value->serialize(); + result = value.serialize(); } auto json = Json::Value::parseString(result); - ASSERT_TRUE(json->is()); + ASSERT_TRUE(json.is()); - auto obj = json->get(); + auto obj = json.get(); - ASSERT_TRUE(obj["person"]->is()); + ASSERT_TRUE(obj["person"].is()); - auto personObj = obj["person"]->get(); + auto personObj = obj["person"].get(); - ASSERT_TRUE(personObj["name"]->is()); - ASSERT_EQ(personObj["name"]->get(), "John"); + ASSERT_TRUE(personObj["name"].is()); + ASSERT_EQ(personObj["name"].get(), "John"); - ASSERT_TRUE(personObj["age"]->is()); - ASSERT_EQ(personObj["age"]->get(), 30); + ASSERT_TRUE(personObj["age"].is()); + ASSERT_EQ(personObj["age"].get(), 30); } TEST(JsonSerializer, SerializeComplexObject) { @@ -202,32 +202,32 @@ TEST(JsonSerializer, SerializeComplexObject) { auto value = Json::object(obj); - result = value->serialize(); + result = value.serialize(); } auto json = Json::Value::parseString(result); - ASSERT_TRUE(json->is()); + ASSERT_TRUE(json.is()); - auto obj = json->get(); - ASSERT_TRUE(obj["name"]->is()); - ASSERT_EQ(obj["name"]->get(), "John"); + auto obj = json.get(); + ASSERT_TRUE(obj["name"].is()); + ASSERT_EQ(obj["name"].get(), "John"); - ASSERT_TRUE(obj["age"]->is()); - ASSERT_EQ(obj["age"]->get(), 30); + ASSERT_TRUE(obj["age"].is()); + ASSERT_EQ(obj["age"].get(), 30); - ASSERT_TRUE(obj["isStudent"]->is()); - ASSERT_EQ(obj["isStudent"]->get(), false); + ASSERT_TRUE(obj["isStudent"].is()); + ASSERT_EQ(obj["isStudent"].get(), false); - ASSERT_TRUE(obj["scores"]->is()); - auto scores = obj["scores"]->get(); + ASSERT_TRUE(obj["scores"].is()); + auto scores = obj["scores"].get(); ASSERT_EQ(scores.size(), 3); - ASSERT_EQ(scores[0]->get(), 85.5); - ASSERT_EQ(scores[1]->get(), 92); - ASSERT_EQ(scores[2]->get(), 78.5); - - ASSERT_TRUE(obj["address"]->is()); - auto address = obj["address"]->get(); - ASSERT_EQ(address["city"]->get(), "New York"); - ASSERT_EQ(address["zip"]->get(), "10001"); + ASSERT_EQ(scores[0].get(), 85.5); + ASSERT_EQ(scores[1].get(), 92); + ASSERT_EQ(scores[2].get(), 78.5); + + ASSERT_TRUE(obj["address"].is()); + auto address = obj["address"].get(); + ASSERT_EQ(address["city"].get(), "New York"); + ASSERT_EQ(address["zip"].get(), "10001"); } From 81c86a1952044d5d12052ad7adaab0c0083d1a3a Mon Sep 17 00:00:00 2001 From: amasson Date: Sat, 2 Nov 2024 00:15:32 +0100 Subject: [PATCH 02/10] json parse in output value #67 --- Engine/Utils/include/Utils/Json.hpp | 4 +-- Engine/Utils/src/Utils/Json.cpp | 10 +++----- Engine/Utils/test/test_Json.cpp | 38 +++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Engine/Utils/include/Utils/Json.hpp b/Engine/Utils/include/Utils/Json.hpp index e1f8b6b..7a52e54 100644 --- a/Engine/Utils/include/Utils/Json.hpp +++ b/Engine/Utils/include/Utils/Json.hpp @@ -46,8 +46,8 @@ struct Value { return std::get(value); } - static Value parseString(const std::string &input); - static Value parseFile(const std::string &path); + static void parseString(const std::string &input, Value &out); + static void parseFile(const std::string &path, Value &out); std::string serialize() const; }; diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index 7a732d1..4ba890e 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -28,15 +28,13 @@ Value::Value(bool b) : value(b) { Value::Value(std::nullptr_t n) : value(n) { } -Value Value::parseString(const std::string &input) { - Value ret; +void Value::parseString(const std::string &input, Value &out) { Parser parser(input); - parser.parse(ret); - return ret; + parser.parse(out); } -Value Value::parseFile(const std::string &path) { - return parseString(Utils::readTextFile(path)); +void Value::parseFile(const std::string &path, Value &out) { + parseString(Utils::readTextFile(path), out); } std::string Value::serialize() const { diff --git a/Engine/Utils/test/test_Json.cpp b/Engine/Utils/test/test_Json.cpp index 846c1d8..9fbc2be 100644 --- a/Engine/Utils/test/test_Json.cpp +++ b/Engine/Utils/test/test_Json.cpp @@ -7,7 +7,8 @@ using namespace Stone; TEST(Json, ParseEmptyObject) { std::string jsonString = "{}"; - auto json = Json::Value::parseString(jsonString); + Json::Value json; + Json::Value::parseString(jsonString, json); ASSERT_TRUE(json.is()); ASSERT_TRUE(json.get().empty()); @@ -16,7 +17,8 @@ TEST(Json, ParseEmptyObject) { TEST(Json, ParseSimpleObject) { std::string jsonString = R"({"name": "John", "age": 30, "isStudent": false})"; - auto json = Json::Value::parseString(jsonString); + Json::Value json; + Json::Value::parseString(jsonString, json); ASSERT_TRUE(json.is()); @@ -34,7 +36,8 @@ TEST(Json, ParseSimpleObject) { TEST(Json, ParseArray) { std::string jsonString = R"([1, "two", true, null])"; - auto json = Json::Value::parseString(jsonString); + Json::Value json; + Json::Value::parseString(jsonString, json); ASSERT_TRUE(json.is()); @@ -56,7 +59,8 @@ TEST(Json, ParseArray) { TEST(Json, ParseNestedObject) { std::string jsonString = R"({"person": {"name": "John", "age": 30}})"; - auto json = Json::Value::parseString(jsonString); + Json::Value json; + Json::Value::parseString(jsonString, json); ASSERT_TRUE(json.is()); @@ -74,13 +78,23 @@ TEST(Json, ParseNestedObject) { TEST(Json, MalformedJsonThrowsException) { std::string jsonString = R"({"name": "John")"; // Missing closing brace - EXPECT_THROW({ auto json = Json::Value::parseString(jsonString); }, std::runtime_error); + EXPECT_THROW( + { + Json::Value json; + Json::Value::parseString(jsonString, json); + }, + std::runtime_error); } TEST(Json, MalformedJsonThrowsException2) { std::string jsonString = R"({"name": John})"; // No quotes around string - EXPECT_THROW({ auto json = Json::Value::parseString(jsonString); }, std::runtime_error); + EXPECT_THROW( + { + Json::Value json; + Json::Value::parseString(jsonString, json); + }, + std::runtime_error); } /* @@ -111,7 +125,8 @@ TEST(JsonSerializer, SerializeSimpleObject) { result = value.serialize(); } - auto json = Json::Value::parseString(result); + Json::Value json; + Json::Value::parseString(result, json); ASSERT_TRUE(json.is()); @@ -137,7 +152,8 @@ TEST(JsonSerializer, SerializeArray) { result = value.serialize(); } - auto json = Json::Value::parseString(result); + Json::Value json; + Json::Value::parseString(result, json); ASSERT_TRUE(json.is()); @@ -168,7 +184,8 @@ TEST(JsonSerializer, SerializeNestedObject) { result = value.serialize(); } - auto json = Json::Value::parseString(result); + Json::Value json; + Json::Value::parseString(result, json); ASSERT_TRUE(json.is()); @@ -205,7 +222,8 @@ TEST(JsonSerializer, SerializeComplexObject) { result = value.serialize(); } - auto json = Json::Value::parseString(result); + Json::Value json; + Json::Value::parseString(result, json); ASSERT_TRUE(json.is()); From 678a7cc96a50f452abc5fd2035f3f643153c6bf7 Mon Sep 17 00:00:00 2001 From: amasson Date: Sat, 2 Nov 2024 00:50:17 +0100 Subject: [PATCH 03/10] clang tidy json #67 --- Engine/Utils/include/Utils/Json.hpp | 6 +++--- Engine/Utils/src/Utils/Json.cpp | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Engine/Utils/include/Utils/Json.hpp b/Engine/Utils/include/Utils/Json.hpp index 7a52e54..479439c 100644 --- a/Engine/Utils/include/Utils/Json.hpp +++ b/Engine/Utils/include/Utils/Json.hpp @@ -20,9 +20,9 @@ struct Value { std::variant value; - explicit Value(Object obj); - explicit Value(Array arr); - explicit Value(std::string str); + explicit Value(const Object &obj); + explicit Value(const Array &arr); + explicit Value(const std::string &str); explicit Value(double num); explicit Value(bool b); explicit Value(std::nullptr_t n = nullptr); diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index 4ba890e..c45f20b 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -10,13 +10,13 @@ namespace Stone::Json { -Value::Value(Object obj) : value(std::move(obj)) { +Value::Value(const Object &obj) : value(std::move(obj)) { } -Value::Value(Array arr) : value(std::move(arr)) { +Value::Value(const Array &arr) : value(std::move(arr)) { } -Value::Value(std::string str) : value(std::move(str)) { +Value::Value(const std::string &str) : value(std::move(str)) { } Value::Value(double num) : value(num) { @@ -163,7 +163,7 @@ void Parser::_parseObject(Value &out) { Object &object(std::get(out.value)); _consume(TokenType::LeftBrace); while (_currentToken.type != TokenType::RightBrace) { - std::string key = _currentToken.value; + const std::string key = _currentToken.value; _consume(TokenType::String); _consume(TokenType::Colon); _parseValue(object[key]); @@ -181,8 +181,7 @@ void Parser::_parseArray(Value &out) { Array &array(std::get(out.value)); _consume(TokenType::LeftBracket); while (_currentToken.type != TokenType::RightBracket) { - array.push_back(Value()); - _parseValue(array.back()); + _parseValue(array.emplace_back()); if (_currentToken.type == TokenType::Comma) { _consume(TokenType::Comma); } else { From d09ea3b7d7e98422c27224fb05f14aeba141d1d3 Mon Sep 17 00:00:00 2001 From: amasson Date: Sat, 2 Nov 2024 00:58:11 +0100 Subject: [PATCH 04/10] Explicit map value reference #67 --- Engine/Utils/src/Utils/Json.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index c45f20b..e1e73ac 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -166,7 +166,8 @@ void Parser::_parseObject(Value &out) { const std::string key = _currentToken.value; _consume(TokenType::String); _consume(TokenType::Colon); - _parseValue(object[key]); + Value &value = object[key]; + _parseValue(value); if (_currentToken.type == TokenType::Comma) { _consume(TokenType::Comma); } else { From 282d92fbdf905f1af9fe87c752e710b8d8ecd9e7 Mon Sep 17 00:00:00 2001 From: amasson Date: Sat, 2 Nov 2024 09:23:55 +0100 Subject: [PATCH 05/10] explicit runtime error #67 --- Engine/Utils/include/Utils/Json.hpp | 7 +++++++ Engine/Utils/src/Utils/Json.cpp | 29 +++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Engine/Utils/include/Utils/Json.hpp b/Engine/Utils/include/Utils/Json.hpp index 479439c..9a95c17 100644 --- a/Engine/Utils/include/Utils/Json.hpp +++ b/Engine/Utils/include/Utils/Json.hpp @@ -27,6 +27,11 @@ struct Value { explicit Value(bool b); explicit Value(std::nullptr_t n = nullptr); + template , T>>> + Value(T &&val) : value(std::forward(val)) { + } + template bool is() const { return std::holds_alternative(value); @@ -74,6 +79,8 @@ enum class TokenType { EndOfFile }; +std::string to_string(TokenType type); + struct Token { TokenType type; std::string value; diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index e1e73ac..66a70ed 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -5,6 +5,7 @@ #include "Utils/FileSystem.hpp" #include "Utils/StringExt.hpp" +#include #include @@ -67,6 +68,24 @@ Value null() { } +std::string to_string(TokenType type) { + switch (type) { + case TokenType::LeftBrace: return "LeftBrace '{'"; + case TokenType::RightBrace: return "RightBrace '}'"; + case TokenType::LeftBracket: return "LeftBracket '['"; + case TokenType::RightBracket: return "RightBracket ']'"; + case TokenType::Comma: return "Comma ','"; + case TokenType::Colon: return "Colon ':'"; + case TokenType::String: return "String"; + case TokenType::Number: return "Number"; + case TokenType::True: return "True"; + case TokenType::False: return "False"; + case TokenType::Null: return "Null"; + case TokenType::EndOfFile: return "EndOfFile"; + default: return "Unknown"; + } +} + Lexer::Lexer(const std::string &input) : _input(input) { } @@ -163,11 +182,13 @@ void Parser::_parseObject(Value &out) { Object &object(std::get(out.value)); _consume(TokenType::LeftBrace); while (_currentToken.type != TokenType::RightBrace) { - const std::string key = _currentToken.value; + const std::string &key = _currentToken.value; _consume(TokenType::String); _consume(TokenType::Colon); - Value &value = object[key]; - _parseValue(value); + object[key] = Value(); + auto obj_it = object.find(key); + assert(obj_it != object.end()); + _parseValue(obj_it->second); if (_currentToken.type == TokenType::Comma) { _consume(TokenType::Comma); } else { @@ -206,7 +227,7 @@ void Parser::_parsePrimitive(Value &out) { void Parser::_consume(TokenType expected) { if (_currentToken.type != expected) { - throw std::runtime_error("Unexpected token in input"); + throw std::runtime_error("Expected " + to_string(expected) + ", but got " + _currentToken.value); } _currentToken = _lexer.nextToken(); } From e5dccab457c316207386f52835477435dc3539cd Mon Sep 17 00:00:00 2001 From: amasson Date: Sat, 2 Nov 2024 09:49:49 +0100 Subject: [PATCH 06/10] remove wrong ref #67 --- Engine/Utils/src/Utils/Json.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index 66a70ed..2f6f30e 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -182,13 +182,10 @@ void Parser::_parseObject(Value &out) { Object &object(std::get(out.value)); _consume(TokenType::LeftBrace); while (_currentToken.type != TokenType::RightBrace) { - const std::string &key = _currentToken.value; + const std::string key = _currentToken.value; // Store the key before consuming the tokens _consume(TokenType::String); _consume(TokenType::Colon); - object[key] = Value(); - auto obj_it = object.find(key); - assert(obj_it != object.end()); - _parseValue(obj_it->second); + _parseValue(object[key]); if (_currentToken.type == TokenType::Comma) { _consume(TokenType::Comma); } else { From 860276d943ed59a1140cb7b84c94f7d0cf4aadf8 Mon Sep 17 00:00:00 2001 From: amasson Date: Sat, 2 Nov 2024 12:39:31 +0100 Subject: [PATCH 07/10] use move #67 --- .../Scene/Assets/AssetResource_AssimpLoad.cpp | 19 ++++++++++--------- Engine/Utils/src/Utils/Json.cpp | 14 ++++++++------ Engine/Utils/test/test_Json.cpp | 16 ++++++++-------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp b/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp index 77f524d..8c4ecce 100644 --- a/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp +++ b/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp @@ -252,8 +252,8 @@ void loadMetadataEntry(const aiMetadataEntry &entry, Json::Value &out) { } case AI_UINT64: { - const double data = *static_cast(entry.mData); - out.value = data; + const uint64_t data = *static_cast(entry.mData); + out.value = static_cast(data); return; } case AI_FLOAT: @@ -271,17 +271,17 @@ void loadMetadataEntry(const aiMetadataEntry &entry, Json::Value &out) { case AI_AIVECTOR3D: { out.value = Json::Array(); - Json::Array &array(std::get(out.value)); + auto &array(std::get(out.value)); const aiVector3D *data = static_cast(entry.mData); - array.push_back(Json::Value(data->x)); - array.push_back(Json::Value(data->y)); - array.push_back(Json::Value(data->z)); + array.emplace_back(data->x); + array.emplace_back(data->y); + array.emplace_back(data->z); return; } case AI_AIMETADATA: { out.value = Json::Object(); - Json::Object &object(std::get(out.value)); + auto &object(std::get(out.value)); const aiMetadata *data = static_cast(entry.mData); for (unsigned int i = 0; i < data->mNumProperties; ++i) { const aiString &key(data->mKeys[i]); @@ -289,11 +289,12 @@ void loadMetadataEntry(const aiMetadataEntry &entry, Json::Value &out) { assert(key.C_Str() != nullptr); loadMetadataEntry(value, object[key.C_Str()]); } + return; } case AI_INT64: { - const double data = *static_cast(entry.mData); - out.value = data; + const int64_t data = *static_cast(entry.mData); + out.value = static_cast(data); return; } case AI_UINT32: diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index 2f6f30e..69c29d5 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -11,13 +11,13 @@ namespace Stone::Json { -Value::Value(const Object &obj) : value(std::move(obj)) { +Value::Value(const Object &obj) : value(obj) { } -Value::Value(const Array &arr) : value(std::move(arr)) { +Value::Value(const Array &arr) : value(arr) { } -Value::Value(const std::string &str) : value(std::move(str)) { +Value::Value(const std::string &str) : value(str) { } Value::Value(double num) : value(num) { @@ -179,13 +179,15 @@ void Parser::_parseValue(Value &out) { void Parser::_parseObject(Value &out) { out.value = Object(); - Object &object(std::get(out.value)); + auto &object(std::get(out.value)); _consume(TokenType::LeftBrace); while (_currentToken.type != TokenType::RightBrace) { const std::string key = _currentToken.value; // Store the key before consuming the tokens _consume(TokenType::String); _consume(TokenType::Colon); - _parseValue(object[key]); + Value value; + _parseValue(value); + object[key] = std::move(value); if (_currentToken.type == TokenType::Comma) { _consume(TokenType::Comma); } else { @@ -197,7 +199,7 @@ void Parser::_parseObject(Value &out) { void Parser::_parseArray(Value &out) { out.value = Array(); - Array &array(std::get(out.value)); + auto &array(std::get(out.value)); _consume(TokenType::LeftBracket); while (_currentToken.type != TokenType::RightBracket) { _parseValue(array.emplace_back()); diff --git a/Engine/Utils/test/test_Json.cpp b/Engine/Utils/test/test_Json.cpp index 9fbc2be..308480a 100644 --- a/Engine/Utils/test/test_Json.cpp +++ b/Engine/Utils/test/test_Json.cpp @@ -116,9 +116,9 @@ TEST(JsonSerializer, SerializeSimpleObject) { { Json::Object obj; - obj["name"] = Json::string("John"); - obj["age"] = Json::number(30.0); - obj["isStudent"] = Json::boolean(false); + obj["name"] = "John"; + obj["age"] = 30.0; + obj["isStudent"] = false; auto value = Json::object(obj); @@ -211,11 +211,11 @@ TEST(JsonSerializer, SerializeComplexObject) { addressObj["zip"] = Json::string("10001"); Json::Object obj; - obj["name"] = Json::string("John"); - obj["age"] = Json::number(30.0); - obj["isStudent"] = Json::boolean(false); - obj["scores"] = Json::array({Json::number(85.5), Json::number(92.0), Json::number(78.5)}); - obj["address"] = Json::object(addressObj); + obj["name"] = "John"; + obj["age"] = 30.0; + obj["isStudent"] = false; + obj["scores"] = Json::array({85.5, 92.0, 78.5}); + obj["address"] = addressObj; auto value = Json::object(obj); From 28c740ceb7dd467e733f91d659b19fdd533e7276 Mon Sep 17 00:00:00 2001 From: amasson Date: Sat, 2 Nov 2024 16:54:33 +0100 Subject: [PATCH 08/10] Purge useless initializers #67 --- Engine/Utils/include/Utils/Json.hpp | 8 ++------ Engine/Utils/src/Utils/Json.cpp | 30 ++++++----------------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/Engine/Utils/include/Utils/Json.hpp b/Engine/Utils/include/Utils/Json.hpp index 9a95c17..1deb0df 100644 --- a/Engine/Utils/include/Utils/Json.hpp +++ b/Engine/Utils/include/Utils/Json.hpp @@ -20,12 +20,8 @@ struct Value { std::variant value; - explicit Value(const Object &obj); - explicit Value(const Array &arr); - explicit Value(const std::string &str); - explicit Value(double num); - explicit Value(bool b); - explicit Value(std::nullptr_t n = nullptr); + Value() : value(nullptr) { + } template , T>>> diff --git a/Engine/Utils/src/Utils/Json.cpp b/Engine/Utils/src/Utils/Json.cpp index 69c29d5..f2e53e6 100644 --- a/Engine/Utils/src/Utils/Json.cpp +++ b/Engine/Utils/src/Utils/Json.cpp @@ -11,24 +11,6 @@ namespace Stone::Json { -Value::Value(const Object &obj) : value(obj) { -} - -Value::Value(const Array &arr) : value(arr) { -} - -Value::Value(const std::string &str) : value(str) { -} - -Value::Value(double num) : value(num) { -} - -Value::Value(bool b) : value(b) { -} - -Value::Value(std::nullptr_t n) : value(n) { -} - void Value::parseString(const std::string &input, Value &out) { Parser parser(input); parser.parse(out); @@ -44,27 +26,27 @@ std::string Value::serialize() const { } Value object(const Object &obj) { - return Value(obj); + return {obj}; } Value array(const Array &arr) { - return Value(arr); + return {arr}; } Value string(const std::string &str) { - return Value(str); + return {str}; } Value number(double num) { - return Value(num); + return {num}; } Value boolean(bool b) { - return Value(b); + return {b}; } Value null() { - return Value(); + return {}; } From 280ec34269deb7bfa2017693c6e4c50c83183c6b Mon Sep 17 00:00:00 2001 From: Ghali Boucetta Date: Sun, 3 Nov 2024 11:39:35 +0100 Subject: [PATCH 09/10] [Workflow] add dispatch event trigger on analyze workflow Signed-off-by: Ghali Boucetta --- .github/workflows/analyze.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 5952f8e..9d5c51e 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -11,6 +11,7 @@ on: - '**/CMakeLists.txt' - '**/.clang-tidy' - '**/.clang-format' + workflow_dispatch: env: home: /home/runner From cd95437390cb742a3d1855d518ed6f1d44d171a2 Mon Sep 17 00:00:00 2001 From: amasson Date: Tue, 5 Nov 2024 00:45:47 +0100 Subject: [PATCH 10/10] Fix parse string metadata #72 --- Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp | 6 ++++++ examples/scop/main.cpp | 1 + 2 files changed, 7 insertions(+) diff --git a/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp b/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp index 8c4ecce..b71c879 100644 --- a/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp +++ b/Engine/Scene/src/Scene/Assets/AssetResource_AssimpLoad.cpp @@ -268,6 +268,12 @@ void loadMetadataEntry(const aiMetadataEntry &entry, Json::Value &out) { out.value = data; return; } + case AI_AISTRING: + { + const aiString *data = static_cast(entry.mData); + out.value = data->C_Str(); + return; + } case AI_AIVECTOR3D: { out.value = Json::Array(); diff --git a/examples/scop/main.cpp b/examples/scop/main.cpp index c49b569..74b5797 100644 --- a/examples/scop/main.cpp +++ b/examples/scop/main.cpp @@ -114,6 +114,7 @@ int main(int argc, char **argv) { auto asset = assetsBundle->loadResource(argv[1]); auto node = asset->getRootNode(); window->getWorld()->addChild(node); + std::cout << Stone::Json::object(asset->getMetadatas()).serialize() << std::endl; node->writeHierarchy(std::cout); }