mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Implemented 'strict' json support
This commit is contained in:
		| @@ -405,6 +405,7 @@ set(lib_HEADERS | ||||
| 	filesystem/ResourcePath.h | ||||
|  | ||||
| 	json/JsonBonus.h | ||||
| 	json/JsonFormatException.h | ||||
| 	json/JsonNode.h | ||||
| 	json/JsonParser.h | ||||
| 	json/JsonRandom.h | ||||
|   | ||||
| @@ -14,6 +14,11 @@ | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| struct Bonus; | ||||
| class ILimiter; | ||||
| class CSelector; | ||||
| class CAddInfo; | ||||
|  | ||||
| namespace JsonUtils | ||||
| { | ||||
| 	DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec); | ||||
|   | ||||
							
								
								
									
										20
									
								
								lib/json/JsonFormatException.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								lib/json/JsonFormatException.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* | ||||
|  * JsonFormatException.h, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| class JsonFormatException : public std::runtime_error | ||||
| { | ||||
| public: | ||||
| 	using runtime_error::runtime_error; | ||||
| }; | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_END | ||||
| @@ -79,8 +79,12 @@ JsonNode::JsonNode(const std::string & string) | ||||
| {} | ||||
|  | ||||
| JsonNode::JsonNode(const std::byte *data, size_t datasize) | ||||
| 	:JsonNode(data, datasize, JsonParsingSettings()) | ||||
| {} | ||||
|  | ||||
| JsonNode::JsonNode(const std::byte *data, size_t datasize, const JsonParsingSettings & parserSettings) | ||||
| { | ||||
| 	JsonParser parser(reinterpret_cast<const char*>(data), datasize); | ||||
| 	JsonParser parser(reinterpret_cast<const char*>(data), datasize, parserSettings); | ||||
| 	*this = parser.parse("<unknown>"); | ||||
| } | ||||
|  | ||||
| @@ -88,7 +92,7 @@ JsonNode::JsonNode(const JsonPath & fileURI) | ||||
| { | ||||
| 	auto file = CResourceHandler::get()->load(fileURI)->readAll(); | ||||
|  | ||||
| 	JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second); | ||||
| 	JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings()); | ||||
| 	*this = parser.parse(fileURI.getName()); | ||||
| } | ||||
|  | ||||
| @@ -96,7 +100,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); | ||||
| 	JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings()); | ||||
| 	*this = parser.parse(fileURI.getName()); | ||||
| } | ||||
|  | ||||
| @@ -104,7 +108,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); | ||||
| 	JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings()); | ||||
| 	*this = parser.parse(fileURI.getName()); | ||||
| 	isValidSyntax = parser.isValid(); | ||||
| } | ||||
|   | ||||
| @@ -17,10 +17,23 @@ class JsonNode; | ||||
| using JsonMap = std::map<std::string, JsonNode>; | ||||
| using JsonVector = std::vector<JsonNode>; | ||||
|  | ||||
| struct Bonus; | ||||
| class CSelector; | ||||
| class CAddInfo; | ||||
| class ILimiter; | ||||
| struct JsonParsingSettings | ||||
| { | ||||
| 	enum class JsonFormatMode | ||||
| 	{ | ||||
| 		JSON, // strict implementation of json format | ||||
| 		JSONC, // json format that also allows comments that start from '//' | ||||
| 		//JSON5 // TODO? | ||||
| 	}; | ||||
|  | ||||
| 	JsonFormatMode mode = JsonFormatMode::JSONC; | ||||
|  | ||||
| 	/// Maximum depth of elements | ||||
| 	uint32_t maxDepth = 30; | ||||
|  | ||||
| 	/// If set to true, parser will throw on any encountered error | ||||
| 	bool strict = false; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE JsonNode | ||||
| { | ||||
| @@ -58,6 +71,7 @@ public: | ||||
|  | ||||
| 	/// Create tree from Json-formatted input | ||||
| 	explicit JsonNode(const std::byte * data, size_t datasize); | ||||
| 	explicit JsonNode(const std::byte * data, size_t datasize, const JsonParsingSettings & parserSettings); | ||||
|  | ||||
| 	/// Create tree from JSON file | ||||
| 	explicit JsonNode(const JsonPath & fileURI); | ||||
|   | ||||
| @@ -11,12 +11,14 @@ | ||||
| #include "StdInc.h" | ||||
| #include "JsonParser.h" | ||||
|  | ||||
| #include "JsonFormatException.h" | ||||
| #include "../TextOperations.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| JsonParser::JsonParser(const char * inputString, size_t stringSize): | ||||
| JsonParser::JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings): | ||||
| 	input(inputString, stringSize), | ||||
| 	settings(settings), | ||||
| 	lineCount(1), | ||||
| 	lineStart(0), | ||||
| 	pos(0) | ||||
| @@ -105,9 +107,13 @@ bool JsonParser::extractWhitespace(bool verbose) | ||||
| 			} | ||||
| 			pos++; | ||||
| 		} | ||||
|  | ||||
| 		if (pos >= input.size() || input[pos] != '/') | ||||
| 			break; | ||||
|  | ||||
| 		if (settings.mode == JsonParsingSettings::JsonFormatMode::JSON) | ||||
| 			error("Comments are not permitted in json!", true); | ||||
|  | ||||
| 		pos++; | ||||
| 		if (pos == input.size()) | ||||
| 			break; | ||||
| @@ -346,9 +352,8 @@ bool JsonParser::extractElement(JsonNode &node, char terminator) | ||||
|  | ||||
| 	if (input[pos] == terminator) | ||||
| 	{ | ||||
| 		//FIXME: MOD COMPATIBILITY: Too many of these right now, re-enable later | ||||
| 		//if (comma) | ||||
| 			//error("Extra comma found!", true); | ||||
| 		if (comma) | ||||
| 			error("Extra comma found!", true); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| @@ -456,6 +461,9 @@ bool JsonParser::extractFloat(JsonNode &node) | ||||
|  | ||||
| bool JsonParser::error(const std::string &message, bool warning) | ||||
| { | ||||
| 	if (settings.strict) | ||||
| 		throw JsonFormatException(message); | ||||
|  | ||||
| 	std::ostringstream stream; | ||||
| 	std::string type(warning?" warning: ":" error: "); | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,8 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
| //Internal class for string -> JsonNode conversion | ||||
| class JsonParser | ||||
| { | ||||
| 	const JsonParsingSettings settings; | ||||
|  | ||||
| 	std::string errors;     // Contains description of all encountered errors | ||||
| 	std::string_view input;      // Input data | ||||
| 	ui32 lineCount; // Currently parsed line, starting from 1 | ||||
| @@ -44,7 +46,7 @@ class JsonParser | ||||
| 	bool error(const std::string &message, bool warning=false); | ||||
|  | ||||
| public: | ||||
| 	JsonParser(const char * inputString, size_t stringSize); | ||||
| 	JsonParser(const char * 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); | ||||
|   | ||||
| @@ -14,6 +14,8 @@ | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| struct Bonus; | ||||
|  | ||||
| namespace spells | ||||
| { | ||||
| namespace effects | ||||
|   | ||||
		Reference in New Issue
	
	Block a user