Ivan Savenko 1 year ago
parent
commit
29860848a5

+ 1 - 2
lib/CArtHandler.cpp

@@ -350,8 +350,7 @@ std::vector<JsonNode> CArtHandler::loadLegacyData()
 		{
 			if(parser.readString() == "x")
 			{
-				artData["slot"].Vector().push_back(JsonNode());
-				artData["slot"].Vector().back().String() = artSlot;
+				artData["slot"].Vector().emplace_back(artSlot);
 			}
 		}
 		artData["class"].String() = classes.at(parser.readString()[0]);

+ 3 - 9
lib/json/JsonBonus.cpp

@@ -13,23 +13,17 @@
 
 #include "JsonValidator.h"
 
-#include "../ScopeGuard.h"
+#include "../CGeneralTextHandler.h"
+#include "../VCMI_Lib.h"
 #include "../bonuses/BonusParams.h"
-#include "../bonuses/Bonus.h"
 #include "../bonuses/Limiters.h"
 #include "../bonuses/Propagators.h"
 #include "../bonuses/Updaters.h"
-#include "../filesystem/Filesystem.h"
-#include "../modding/IdentifierStorage.h"
-#include "../VCMI_Lib.h" //for identifier resolution
-#include "../CGeneralTextHandler.h"
 #include "../constants/StringConstants.h"
-#include "../battle/BattleHex.h"
+#include "../modding/IdentifierStorage.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-static const JsonNode nullNode;
-
 static void loadBonusSubtype(BonusSubtypeID & subtype, BonusType type, const JsonNode & node)
 {
 	if (node.isNull())

+ 24 - 16
lib/json/JsonNode.cpp

@@ -15,8 +15,6 @@
 #include "JsonWriter.h"
 #include "filesystem/Filesystem.h"
 
-namespace
-{
 // to avoid duplicating const and non-const code
 template<typename Node>
 Node & resolvePointer(Node & in, const std::string & pointer)
@@ -45,15 +43,14 @@ Node & resolvePointer(Node & in, const std::string & pointer)
 	}
 	return in[entry].resolvePointer(remainer);
 }
-}
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+static const JsonNode nullNode;
+
 class LibClasses;
 class CModHandler;
 
-static const JsonNode nullNode;
-
 JsonNode::JsonNode(bool boolean)
 	: data(boolean)
 {
@@ -91,15 +88,20 @@ JsonNode::JsonNode(const std::byte * data, size_t datasize)
 
 JsonNode::JsonNode(const std::byte * data, size_t datasize, const JsonParsingSettings & parserSettings)
 {
-	JsonParser parser(reinterpret_cast<const char *>(data), datasize, parserSettings);
+	JsonParser parser(data, datasize, parserSettings);
 	*this = parser.parse("<unknown>");
 }
 
 JsonNode::JsonNode(const JsonPath & fileURI)
+	:JsonNode(fileURI, JsonParsingSettings())
+{
+}
+
+JsonNode::JsonNode(const JsonPath & fileURI, const JsonParsingSettings & parserSettings)
 {
 	auto file = CResourceHandler::get()->load(fileURI)->readAll();
 
-	JsonParser parser(reinterpret_cast<char *>(file.first.get()), file.second, JsonParsingSettings());
+	JsonParser parser(reinterpret_cast<std::byte *>(file.first.get()), file.second, parserSettings);
 	*this = parser.parse(fileURI.getName());
 }
 
@@ -107,7 +109,7 @@ JsonNode::JsonNode(const JsonPath & fileURI, const std::string & idx)
 {
 	auto file = CResourceHandler::get(idx)->load(fileURI)->readAll();
 
-	JsonParser parser(reinterpret_cast<char *>(file.first.get()), file.second, JsonParsingSettings());
+	JsonParser parser(reinterpret_cast<std::byte *>(file.first.get()), file.second, JsonParsingSettings());
 	*this = parser.parse(fileURI.getName());
 }
 
@@ -115,7 +117,7 @@ JsonNode::JsonNode(const JsonPath & fileURI, bool & isValidSyntax)
 {
 	auto file = CResourceHandler::get()->load(fileURI)->readAll();
 
-	JsonParser parser(reinterpret_cast<char *>(file.first.get()), file.second, JsonParsingSettings());
+	JsonParser parser(reinterpret_cast<std::byte *>(file.first.get()), file.second, JsonParsingSettings());
 	*this = parser.parse(fileURI.getName());
 	isValidSyntax = parser.isValid();
 }
@@ -206,7 +208,7 @@ void JsonNode::setType(JsonType Type)
 			data = JsonData(false);
 			break;
 		case JsonType::DATA_FLOAT:
-			data = JsonData(static_cast<double>(0.0));
+			data = JsonData(0.0);
 			break;
 		case JsonType::DATA_STRING:
 			data = JsonData(std::string());
@@ -355,9 +357,10 @@ JsonMap & JsonNode::Struct()
 	return std::get<JsonMap>(data);
 }
 
-const bool boolDefault = false;
 bool JsonNode::Bool() const
 {
+	static const bool boolDefault = false;
+
 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_BOOL);
 
 	if(getType() == JsonType::DATA_BOOL)
@@ -366,9 +369,10 @@ bool JsonNode::Bool() const
 	return boolDefault;
 }
 
-const double floatDefault = 0;
 double JsonNode::Float() const
 {
+	static const double floatDefault = 0;
+
 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_INTEGER || getType() == JsonType::DATA_FLOAT);
 
 	if(getType() == JsonType::DATA_FLOAT)
@@ -380,9 +384,10 @@ double JsonNode::Float() const
 	return floatDefault;
 }
 
-const si64 integerDefault = 0;
 si64 JsonNode::Integer() const
 {
+	static const si64 integerDefault = 0;
+
 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_INTEGER || getType() == JsonType::DATA_FLOAT);
 
 	if(getType() == JsonType::DATA_INTEGER)
@@ -394,9 +399,10 @@ si64 JsonNode::Integer() const
 	return integerDefault;
 }
 
-const std::string stringDefault = std::string();
 const std::string & JsonNode::String() const
 {
+	static const std::string stringDefault = std::string();
+
 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRING);
 
 	if(getType() == JsonType::DATA_STRING)
@@ -405,9 +411,10 @@ const std::string & JsonNode::String() const
 	return stringDefault;
 }
 
-const JsonVector vectorDefault = JsonVector();
 const JsonVector & JsonNode::Vector() const
 {
+	static const JsonVector vectorDefault = JsonVector();
+
 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_VECTOR);
 
 	if(getType() == JsonType::DATA_VECTOR)
@@ -416,9 +423,10 @@ const JsonVector & JsonNode::Vector() const
 	return vectorDefault;
 }
 
-const JsonMap mapDefault = JsonMap();
 const JsonMap & JsonNode::Struct() const
 {
+	static const JsonMap mapDefault = JsonMap();
+
 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRUCT);
 
 	if(getType() == JsonType::DATA_STRUCT)

+ 1 - 0
lib/json/JsonNode.h

@@ -76,6 +76,7 @@ public:
 
 	/// Create tree from JSON file
 	explicit JsonNode(const JsonPath & fileURI);
+	explicit JsonNode(const JsonPath & fileURI, const JsonParsingSettings & parserSettings);
 	explicit JsonNode(const JsonPath & fileURI, const std::string & modName);
 	explicit JsonNode(const JsonPath & fileURI, bool & isValidSyntax);
 

+ 21 - 17
lib/json/JsonParser.cpp

@@ -11,16 +11,17 @@
 #include "StdInc.h"
 #include "JsonParser.h"
 
+#include "../ScopeGuard.h"
 #include "../TextOperations.h"
 #include "JsonFormatException.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-JsonParser::JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings)
-	: input(inputString, stringSize)
-	, settings(settings)
-	, currentDepth(0)
+JsonParser::JsonParser(const std::byte * inputString, size_t stringSize, const JsonParsingSettings & settings)
+	: settings(settings)
+	, input(reinterpret_cast<const char *>(inputString), stringSize)
 	, lineCount(1)
+	, currentDepth(0)
 	, lineStart(0)
 	, pos(0)
 {
@@ -258,7 +259,6 @@ bool JsonParser::extractLiteral(std::string & literal)
 		pos++;
 	}
 
-	pos += literal.size();
 	return true;
 }
 
@@ -309,10 +309,14 @@ bool JsonParser::extractStruct(JsonNode & node)
 	node.setType(JsonNode::JsonType::DATA_STRUCT);
 
 	if(currentDepth > settings.maxDepth)
-		error("Macimum allowed depth of json structure has been reached", true);
+		error("Maximum allowed depth of json structure has been reached", true);
 
-	currentDepth++;
 	pos++;
+	currentDepth++;
+	auto guard = vstd::makeScopeGuard([this]()
+	{
+		currentDepth--;
+	});
 
 	if(!extractWhitespace())
 		return false;
@@ -393,6 +397,11 @@ bool JsonParser::extractArray(JsonNode & node)
 		error("Macimum allowed depth of json structure has been reached", true);
 
 	currentDepth++;
+	auto guard = vstd::makeScopeGuard([this]()
+	{
+		currentDepth--;
+	});
+
 	pos++;
 	node.setType(JsonNode::JsonType::DATA_VECTOR);
 
@@ -441,11 +450,9 @@ bool JsonParser::extractElement(JsonNode & node, char terminator)
 
 	if(input[pos] == terminator)
 	{
-		if(comma)
-		{
-			if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
-				error("Extra comma found!", true);
-		}
+		if(comma && settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
+			error("Extra comma found!", true);
+
 		return true;
 	}
 
@@ -500,11 +507,8 @@ bool JsonParser::extractFloat(JsonNode & node)
 		pos++;
 		double fractMult = 0.1;
 
-		if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
-		{
-			if(input[pos] < '0' || input[pos] > '9')
-				return error("Decimal part expected!");
-		}
+		if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5 && (input[pos] < '0' || input[pos] > '9'))
+			return error("Decimal part expected!");
 
 		while(input[pos] >= '0' && input[pos] <= '9')
 		{

+ 1 - 1
lib/json/JsonParser.h

@@ -48,7 +48,7 @@ class JsonParser
 	bool error(const std::string & message, bool warning = false);
 
 public:
-	JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings);
+	JsonParser(const std::byte * inputString, size_t stringSize, const JsonParsingSettings & settings);
 
 	/// do actual parsing. filename is name of file that will printed to console if any errors were found
 	JsonNode parse(const std::string & fileName);

+ 2 - 2
lib/json/JsonRandom.cpp

@@ -235,9 +235,9 @@ VCMI_LIB_NAMESPACE_BEGIN
 					filteredAnyOf.insert(subset.begin(), subset.end());
 				}
 
-				vstd::erase_if(filteredTypes, [&](const IdentifierType & value)
+				vstd::erase_if(filteredTypes, [&filteredAnyOf](const IdentifierType & filteredValue)
 				{
-					return filteredAnyOf.count(value) == 0;
+					return filteredAnyOf.count(filteredValue) == 0;
 				});
 			}
 

+ 0 - 11
lib/json/JsonUtils.cpp

@@ -13,18 +13,7 @@
 
 #include "JsonValidator.h"
 
-#include "../ScopeGuard.h"
-#include "../bonuses/BonusParams.h"
-#include "../bonuses/Bonus.h"
-#include "../bonuses/Limiters.h"
-#include "../bonuses/Propagators.h"
-#include "../bonuses/Updaters.h"
 #include "../filesystem/Filesystem.h"
-#include "../modding/IdentifierStorage.h"
-#include "../VCMI_Lib.h" //for identifier resolution
-#include "../CGeneralTextHandler.h"
-#include "../constants/StringConstants.h"
-#include "../battle/BattleHex.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 11 - 10
lib/json/JsonValidator.cpp

@@ -81,7 +81,7 @@ namespace
 
 		std::string allOfCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
-			return schemaListCheck(validator, baseSchema, schema, data, "Failed to pass all schemas", [&](size_t count)
+			return schemaListCheck(validator, baseSchema, schema, data, "Failed to pass all schemas", [&schema](size_t count)
 			{
 				return count == schema.Vector().size();
 			});
@@ -89,7 +89,7 @@ namespace
 
 		std::string anyOfCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
-			return schemaListCheck(validator, baseSchema, schema, data, "Failed to pass any schema", [&](size_t count)
+			return schemaListCheck(validator, baseSchema, schema, data, "Failed to pass any schema", [](size_t count)
 			{
 				return count > 0;
 			});
@@ -97,7 +97,7 @@ namespace
 
 		std::string oneOfCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
-			return schemaListCheck(validator, baseSchema, schema, data, "Failed to pass exactly one schema", [&](size_t count)
+			return schemaListCheck(validator, baseSchema, schema, data, "Failed to pass exactly one schema", [](size_t count)
 			{
 				return count == 1;
 			});
@@ -228,7 +228,7 @@ namespace
 
 		std::string multipleOfCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
-			double result = data.Float() / schema.Float();
+			double result = data.Integer() / schema.Integer();
 			if (!vstd::isAlmostEqual(floor(result), result))
 				return validator.makeErrorMessage((boost::format("Value is not divisible by %d") % schema.Float()).str());
 			return "";
@@ -241,7 +241,7 @@ namespace
 		{
 			validator.currentPath.emplace_back();
 			validator.currentPath.back().Float() = static_cast<double>(index);
-			auto onExit = vstd::makeScopeGuard([&]()
+			auto onExit = vstd::makeScopeGuard([&validator]()
 			{
 				validator.currentPath.pop_back();
 			});
@@ -390,7 +390,7 @@ namespace
 		{
 			validator.currentPath.emplace_back();
 			validator.currentPath.back().String() = nodeName;
-			auto onExit = vstd::makeScopeGuard([&]()
+			auto onExit = vstd::makeScopeGuard([&validator]()
 			{
 				validator.currentPath.pop_back();
 			});
@@ -531,6 +531,9 @@ namespace
 		ret["title"] = Common::emptyCheck;
 		ret["$schema"] = Common::emptyCheck;
 		ret["default"] = Common::emptyCheck;
+		ret["defaultIOS"] = Common::emptyCheck;
+		ret["defaultAndroid"] = Common::emptyCheck;
+		ret["defaultWindows"] = Common::emptyCheck;
 		ret["description"] = Common::emptyCheck;
 		ret["definitions"] = Common::emptyCheck;
 
@@ -643,7 +646,7 @@ namespace Validation
 	std::string check(const std::string & schemaName, const JsonNode & data, ValidationData & validator)
 	{
 		validator.usedSchemas.push_back(schemaName);
-		auto onscopeExit = vstd::makeScopeGuard([&]()
+		auto onscopeExit = vstd::makeScopeGuard([&validator]()
 		{
 			validator.usedSchemas.pop_back();
 		});
@@ -659,8 +662,6 @@ namespace Validation
 			auto checker = knownFields.find(entry.first);
 			if (checker != knownFields.end())
 				errors += checker->second(validator, schema, entry.second, data);
-			//else
-			//	errors += validator.makeErrorMessage("Unknown entry in schema " + entry.first);
 		}
 		return errors;
 	}
@@ -687,7 +688,7 @@ namespace Validation
 
 	const TFormatMap & getKnownFormats()
 	{
-		static TFormatMap knownFormats = createFormatMap();
+		static const TFormatMap knownFormats = createFormatMap();
 		return knownFormats;
 	}
 

+ 3 - 3
lib/json/JsonWriter.cpp

@@ -60,7 +60,7 @@ void JsonWriter::writeEntry(JsonVector::const_iterator entry)
 void JsonWriter::writeString(const std::string & string)
 {
 	static const std::string escaped = "\"\\\b\f\n\r\t";
-	static const std::array escaped_code = {'\"', '\\', 'b', 'f', 'n', 'r', 't'};
+	static const std::array escapedCode = {'\"', '\\', 'b', 'f', 'n', 'r', 't'};
 
 	out << '\"';
 	size_t pos = 0;
@@ -68,7 +68,7 @@ void JsonWriter::writeString(const std::string & string)
 	for(; pos < string.size(); pos++)
 	{
 		//we need to check if special character was been already escaped
-		if((string[pos] == '\\') && (pos + 1 < string.size()) && (std::find(escaped_code.begin(), escaped_code.end(), string[pos + 1]) != escaped_code.end()))
+		if((string[pos] == '\\') && (pos + 1 < string.size()) && (std::find(escapedCode.begin(), escapedCode.end(), string[pos + 1]) != escapedCode.end()))
 		{
 			pos++; //write unchanged, next simbol also checked
 		}
@@ -79,7 +79,7 @@ void JsonWriter::writeString(const std::string & string)
 			if(escapedPos != std::string::npos)
 			{
 				out.write(string.data() + start, pos - start);
-				out << '\\' << escaped_code[escapedPos];
+				out << '\\' << escapedCode[escapedPos];
 				start = pos + 1;
 			}
 		}

+ 1 - 1
lib/mapObjects/ObjectTemplate.cpp

@@ -354,7 +354,7 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const
 			JsonVector & data = node["allowedTerrains"].Vector();
 
 			for(auto type : allowedTerrains)
-				data.push_back(JsonNode(VLC->terrainTypeHandler->getById(type)->getJsonKey()));
+				data.emplace_back(VLC->terrainTypeHandler->getById(type)->getJsonKey());
 		}
 	}
 

+ 4 - 1
lib/modding/CModHandler.cpp

@@ -226,7 +226,10 @@ void CModHandler::loadOneMod(std::string modName, const std::string & parent, co
 
 	if(CResourceHandler::get("initial")->existsResource(CModInfo::getModFile(modFullName)))
 	{
-		CModInfo mod(modFullName, modSettings[modName], JsonNode(CModInfo::getModFile(modFullName)));
+		JsonParsingSettings settings;
+		settings.mode = JsonParsingSettings::JsonFormatMode::JSON; // TODO: remove once Android launcher with its strict parser is gone
+
+		CModInfo mod(modFullName, modSettings[modName], JsonNode(CModInfo::getModFile(modFullName), settings));
 		if (!parent.empty()) // this is submod, add parent to dependencies
 			mod.dependencies.insert(parent);
 

+ 2 - 2
test/scripting/LuaSpellEffectAPITest.cpp

@@ -84,8 +84,8 @@ TEST_F(LuaSpellEffectAPITest, DISABLED_ApplicableOnLeftSideOfField)
 	BattleHex hex(2,2);
 
 	JsonNode first;
-	first.Vector().push_back(JsonNode(hex.hex));
-	first.Vector().push_back(JsonNode());
+	first.Vector().emplace_back(hex.hex);
+	first.Vector().emplace_back();
 
 	JsonNode targets;
 	targets.Vector().push_back(first);

+ 6 - 6
test/scripting/LuaSpellEffectTest.cpp

@@ -154,12 +154,12 @@ TEST_F(LuaSpellEffectTest, ApplicableTargetRedirected)
 
 
 	JsonNode first;
-	first.Vector().push_back(JsonNode(hex1.hex));
-	first.Vector().push_back(JsonNode(id1));
+	first.Vector().emplace_back(hex1.hex);
+	first.Vector().emplace_back(id1);
 
 	JsonNode second;
-	second.Vector().push_back(JsonNode(hex2.hex));
-	second.Vector().push_back(JsonNode(-1));
+	second.Vector().emplace_back(hex2.hex);
+	second.Vector().emplace_back(-1);
 
 	JsonNode targets;
 	targets.Vector().push_back(first);
@@ -193,8 +193,8 @@ TEST_F(LuaSpellEffectTest, ApplyRedirected)
 	subject->apply(&serverMock, &mechanicsMock, target);
 
 	JsonNode first;
-	first.Vector().push_back(JsonNode(hex1.hex));
-	first.Vector().push_back(JsonNode(id1));
+	first.Vector().emplace_back(hex1.hex);
+	first.Vector().emplace_back(id1);
 
 	JsonNode targets;
 	targets.Vector().push_back(first);