mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Unify formatting
This commit is contained in:
		| @@ -11,9 +11,9 @@ | ||||
| #include "StdInc.h" | ||||
| #include "JsonNode.h" | ||||
|  | ||||
| #include "filesystem/Filesystem.h" | ||||
| #include "JsonParser.h" | ||||
| #include "JsonWriter.h" | ||||
| #include "filesystem/Filesystem.h" | ||||
|  | ||||
| namespace | ||||
| { | ||||
| @@ -40,7 +40,7 @@ Node & resolvePointer(Node & in, const std::string & pointer) | ||||
|  | ||||
| 		auto index = boost::lexical_cast<size_t>(entry); | ||||
|  | ||||
| 		if (in.Vector().size() > index) | ||||
| 		if(in.Vector().size() > index) | ||||
| 			return in.Vector()[index].resolvePointer(remainer); | ||||
| 	} | ||||
| 	return in[entry].resolvePointer(remainer); | ||||
| @@ -55,36 +55,43 @@ class CModHandler; | ||||
| static const JsonNode nullNode; | ||||
|  | ||||
| JsonNode::JsonNode(bool boolean) | ||||
| 	:data(boolean) | ||||
| {} | ||||
| 	: data(boolean) | ||||
| { | ||||
| } | ||||
|  | ||||
| JsonNode::JsonNode(int32_t number) | ||||
| 	:data(static_cast<int64_t>(number)) | ||||
| {} | ||||
| 	: data(static_cast<int64_t>(number)) | ||||
| { | ||||
| } | ||||
|  | ||||
| JsonNode::JsonNode(uint32_t number) | ||||
| 	:data(static_cast<int64_t>(number)) | ||||
| {} | ||||
| 	: data(static_cast<int64_t>(number)) | ||||
| { | ||||
| } | ||||
|  | ||||
| JsonNode::JsonNode(int64_t number) | ||||
| 	:data(number) | ||||
| {} | ||||
| 	: data(number) | ||||
| { | ||||
| } | ||||
|  | ||||
| JsonNode::JsonNode(double number) | ||||
| 	:data(number) | ||||
| {} | ||||
| 	: data(number) | ||||
| { | ||||
| } | ||||
|  | ||||
| JsonNode::JsonNode(const std::string & string) | ||||
| 	:data(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) | ||||
| 	: data(string) | ||||
| { | ||||
| 	JsonParser parser(reinterpret_cast<const char*>(data), datasize, parserSettings); | ||||
| } | ||||
|  | ||||
| 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, parserSettings); | ||||
| 	*this = parser.parse("<unknown>"); | ||||
| } | ||||
|  | ||||
| @@ -92,33 +99,33 @@ JsonNode::JsonNode(const JsonPath & fileURI) | ||||
| { | ||||
| 	auto file = CResourceHandler::get()->load(fileURI)->readAll(); | ||||
|  | ||||
| 	JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings()); | ||||
| 	JsonParser parser(reinterpret_cast<char *>(file.first.get()), file.second, JsonParsingSettings()); | ||||
| 	*this = parser.parse(fileURI.getName()); | ||||
| } | ||||
|  | ||||
| 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<char *>(file.first.get()), file.second, JsonParsingSettings()); | ||||
| 	*this = parser.parse(fileURI.getName()); | ||||
| } | ||||
|  | ||||
| JsonNode::JsonNode(const JsonPath & fileURI, bool &isValidSyntax) | ||||
| 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<char *>(file.first.get()), file.second, JsonParsingSettings()); | ||||
| 	*this = parser.parse(fileURI.getName()); | ||||
| 	isValidSyntax = parser.isValid(); | ||||
| } | ||||
|  | ||||
| bool JsonNode::operator == (const JsonNode &other) const | ||||
| bool JsonNode::operator==(const JsonNode & other) const | ||||
| { | ||||
| 	return data == other.data; | ||||
| } | ||||
|  | ||||
| bool JsonNode::operator != (const JsonNode &other) const | ||||
| bool JsonNode::operator!=(const JsonNode & other) const | ||||
| { | ||||
| 	return !(*this == other); | ||||
| } | ||||
| @@ -146,18 +153,20 @@ bool JsonNode::getOverrideFlag() const | ||||
| void JsonNode::setModScope(const std::string & metadata, bool recursive) | ||||
| { | ||||
| 	modScope = metadata; | ||||
| 	if (recursive) | ||||
| 	if(recursive) | ||||
| 	{ | ||||
| 		switch (getType()) | ||||
| 		switch(getType()) | ||||
| 		{ | ||||
| 			break; case JsonType::DATA_VECTOR: | ||||
| 			break; | ||||
| 			case JsonType::DATA_VECTOR: | ||||
| 			{ | ||||
| 				for(auto & node : Vector()) | ||||
| 				{ | ||||
| 					node.setModScope(metadata); | ||||
| 				} | ||||
| 			} | ||||
| 			break; case JsonType::DATA_STRUCT: | ||||
| 			break; | ||||
| 			case JsonType::DATA_STRUCT: | ||||
| 			{ | ||||
| 				for(auto & node : Struct()) | ||||
| 				{ | ||||
| @@ -170,7 +179,7 @@ void JsonNode::setModScope(const std::string & metadata, bool recursive) | ||||
|  | ||||
| void JsonNode::setType(JsonType Type) | ||||
| { | ||||
| 	if (getType() == Type) | ||||
| 	if(getType() == Type) | ||||
| 		return; | ||||
|  | ||||
| 	//float<->int conversion | ||||
| @@ -190,13 +199,27 @@ void JsonNode::setType(JsonType Type) | ||||
| 	//Set new node type | ||||
| 	switch(Type) | ||||
| 	{ | ||||
| 		break; case JsonType::DATA_NULL:    data = JsonData(); | ||||
| 		break; case JsonType::DATA_BOOL:    data = JsonData(false); | ||||
| 		break; case JsonType::DATA_FLOAT:   data = JsonData(static_cast<double>(0.0)); | ||||
| 		break; case JsonType::DATA_STRING:  data = JsonData(std::string()); | ||||
| 		break; case JsonType::DATA_VECTOR:  data = JsonData(JsonVector()); | ||||
| 		break; case JsonType::DATA_STRUCT:  data = JsonData(JsonMap()); | ||||
| 		break; case JsonType::DATA_INTEGER: data = JsonData(static_cast<si64>(0)); | ||||
| 		case JsonType::DATA_NULL: | ||||
| 			data = JsonData(); | ||||
| 			break; | ||||
| 		case JsonType::DATA_BOOL: | ||||
| 			data = JsonData(false); | ||||
| 			break; | ||||
| 		case JsonType::DATA_FLOAT: | ||||
| 			data = JsonData(static_cast<double>(0.0)); | ||||
| 			break; | ||||
| 		case JsonType::DATA_STRING: | ||||
| 			data = JsonData(std::string()); | ||||
| 			break; | ||||
| 		case JsonType::DATA_VECTOR: | ||||
| 			data = JsonData(JsonVector()); | ||||
| 			break; | ||||
| 		case JsonType::DATA_STRUCT: | ||||
| 			data = JsonData(JsonMap()); | ||||
| 			break; | ||||
| 		case JsonType::DATA_INTEGER: | ||||
| 			data = JsonData(static_cast<si64>(0)); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -229,18 +252,18 @@ bool JsonNode::containsBaseData() const | ||||
| { | ||||
| 	switch(getType()) | ||||
| 	{ | ||||
| 	case JsonType::DATA_NULL: | ||||
| 		return false; | ||||
| 	case JsonType::DATA_STRUCT: | ||||
| 		for(const auto & elem : Struct()) | ||||
| 		{ | ||||
| 			if(elem.second.containsBaseData()) | ||||
| 				return true; | ||||
| 		} | ||||
| 		return false; | ||||
| 	default: | ||||
| 		//other types (including vector) cannot be extended via merge | ||||
| 		return true; | ||||
| 		case JsonType::DATA_NULL: | ||||
| 			return false; | ||||
| 		case JsonType::DATA_STRUCT: | ||||
| 			for(const auto & elem : Struct()) | ||||
| 			{ | ||||
| 				if(elem.second.containsBaseData()) | ||||
| 					return true; | ||||
| 			} | ||||
| 			return false; | ||||
| 		default: | ||||
| 			//other types (including vector) cannot be extended via merge | ||||
| 			return true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -248,14 +271,14 @@ bool JsonNode::isCompact() const | ||||
| { | ||||
| 	switch(getType()) | ||||
| 	{ | ||||
| 	case JsonType::DATA_VECTOR: | ||||
| 		for(const JsonNode & elem : Vector()) | ||||
| 		{ | ||||
| 			if(!elem.isCompact()) | ||||
| 				return false; | ||||
| 		} | ||||
| 		return true; | ||||
| 	case JsonType::DATA_STRUCT: | ||||
| 		case JsonType::DATA_VECTOR: | ||||
| 			for(const JsonNode & elem : Vector()) | ||||
| 			{ | ||||
| 				if(!elem.isCompact()) | ||||
| 					return false; | ||||
| 			} | ||||
| 			return true; | ||||
| 		case JsonType::DATA_STRUCT: | ||||
| 		{ | ||||
| 			auto propertyCount = Struct().size(); | ||||
| 			if(propertyCount == 0) | ||||
| @@ -263,9 +286,9 @@ bool JsonNode::isCompact() const | ||||
| 			else if(propertyCount == 1) | ||||
| 				return Struct().begin()->second.isCompact(); | ||||
| 		} | ||||
| 		return false; | ||||
| 	default: | ||||
| 		return true; | ||||
| 			return false; | ||||
| 		default: | ||||
| 			return true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -285,7 +308,7 @@ bool JsonNode::TryBoolFromString(bool & success) const | ||||
|  | ||||
| 		if(success) | ||||
| 			return true; | ||||
| 		 | ||||
|  | ||||
| 		success = boolParamStr == "false"; | ||||
| 	} | ||||
| 	return false; | ||||
| @@ -337,7 +360,7 @@ bool JsonNode::Bool() const | ||||
| { | ||||
| 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_BOOL); | ||||
|  | ||||
| 	if (getType() == JsonType::DATA_BOOL) | ||||
| 	if(getType() == JsonType::DATA_BOOL) | ||||
| 		return std::get<bool>(data); | ||||
|  | ||||
| 	return boolDefault; | ||||
| @@ -376,7 +399,7 @@ const std::string & JsonNode::String() const | ||||
| { | ||||
| 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRING); | ||||
|  | ||||
| 	if (getType() == JsonType::DATA_STRING) | ||||
| 	if(getType() == JsonType::DATA_STRING) | ||||
| 		return std::get<std::string>(data); | ||||
|  | ||||
| 	return stringDefault; | ||||
| @@ -387,7 +410,7 @@ const JsonVector & JsonNode::Vector() const | ||||
| { | ||||
| 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_VECTOR); | ||||
|  | ||||
| 	if (getType() == JsonType::DATA_VECTOR) | ||||
| 	if(getType() == JsonType::DATA_VECTOR) | ||||
| 		return std::get<JsonVector>(data); | ||||
|  | ||||
| 	return vectorDefault; | ||||
| @@ -398,7 +421,7 @@ const JsonMap & JsonNode::Struct() const | ||||
| { | ||||
| 	assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRUCT); | ||||
|  | ||||
| 	if (getType() == JsonType::DATA_STRUCT) | ||||
| 	if(getType() == JsonType::DATA_STRUCT) | ||||
| 		return std::get<JsonMap>(data); | ||||
|  | ||||
| 	return mapDefault; | ||||
| @@ -412,32 +435,32 @@ JsonNode & JsonNode::operator[](const std::string & child) | ||||
| const JsonNode & JsonNode::operator[](const std::string & child) const | ||||
| { | ||||
| 	auto it = Struct().find(child); | ||||
| 	if (it != Struct().end()) | ||||
| 	if(it != Struct().end()) | ||||
| 		return it->second; | ||||
| 	return nullNode; | ||||
| } | ||||
|  | ||||
| JsonNode & JsonNode::operator[](size_t child) | ||||
| { | ||||
| 	if (child >= Vector().size() ) | ||||
| 	if(child >= Vector().size()) | ||||
| 		Vector().resize(child + 1); | ||||
| 	return Vector()[child]; | ||||
| } | ||||
|  | ||||
| const JsonNode & JsonNode::operator[](size_t child) const | ||||
| { | ||||
| 	if (child < Vector().size() ) | ||||
| 	if(child < Vector().size()) | ||||
| 		return Vector()[child]; | ||||
|  | ||||
| 	return nullNode; | ||||
| } | ||||
|  | ||||
| const JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer) const | ||||
| const JsonNode & JsonNode::resolvePointer(const std::string & jsonPointer) const | ||||
| { | ||||
| 	return ::resolvePointer(*this, jsonPointer); | ||||
| } | ||||
|  | ||||
| JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer) | ||||
| JsonNode & JsonNode::resolvePointer(const std::string & jsonPointer) | ||||
| { | ||||
| 	return ::resolvePointer(*this, jsonPointer); | ||||
| } | ||||
| @@ -445,7 +468,7 @@ JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer) | ||||
| std::vector<std::byte> JsonNode::toBytes() const | ||||
| { | ||||
| 	std::string jsonString = toString(); | ||||
| 	auto dataBegin = reinterpret_cast<const std::byte*>(jsonString.data()); | ||||
| 	auto dataBegin = reinterpret_cast<const std::byte *>(jsonString.data()); | ||||
| 	auto dataEnd = dataBegin + jsonString.size(); | ||||
| 	std::vector<std::byte> result(dataBegin, dataEnd); | ||||
| 	return result; | ||||
|   | ||||
| @@ -58,6 +58,7 @@ private: | ||||
| 	std::string modScope; | ||||
|  | ||||
| 	bool overrideFlag = false; | ||||
|  | ||||
| public: | ||||
| 	JsonNode() = default; | ||||
|  | ||||
| @@ -78,8 +79,8 @@ public: | ||||
| 	explicit JsonNode(const JsonPath & fileURI, const std::string & modName); | ||||
| 	explicit JsonNode(const JsonPath & fileURI, bool & isValidSyntax); | ||||
|  | ||||
| 	bool operator == (const JsonNode &other) const; | ||||
| 	bool operator != (const JsonNode &other) const; | ||||
| 	bool operator==(const JsonNode & other) const; | ||||
| 	bool operator!=(const JsonNode & other) const; | ||||
|  | ||||
| 	const std::string & getModScope() const; | ||||
| 	void setModScope(const std::string & metadata, bool recursive = true); | ||||
| @@ -139,17 +140,18 @@ public: | ||||
| 	const JsonNode & operator[](const std::string & child) const; | ||||
|  | ||||
| 	JsonNode & operator[](size_t child); | ||||
| 	const JsonNode & operator[](size_t  child) const; | ||||
| 	const JsonNode & operator[](size_t child) const; | ||||
|  | ||||
| 	std::string toCompactString() const; | ||||
| 	std::string toString() const; | ||||
| 	std::vector<std::byte> toBytes() const; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h) | ||||
| 	template<typename Handler> | ||||
| 	void serialize(Handler & h) | ||||
| 	{ | ||||
| 		h & modScope; | ||||
|  | ||||
| 		if (h.version >= Handler::Version::JSON_FLAGS) | ||||
| 		if(h.version >= Handler::Version::JSON_FLAGS) | ||||
| 		{ | ||||
| 			h & overrideFlag; | ||||
| 		} | ||||
| @@ -187,15 +189,15 @@ inline void convert(std::string & value, const JsonNode & node) | ||||
| 	value = node.String(); | ||||
| } | ||||
|  | ||||
| template <typename Type> | ||||
| void convert(std::map<std::string,Type> & value, const JsonNode & node) | ||||
| template<typename Type> | ||||
| void convert(std::map<std::string, Type> & value, const JsonNode & node) | ||||
| { | ||||
| 	value.clear(); | ||||
| 	for (const JsonMap::value_type & entry : node.Struct()) | ||||
| 	for(const JsonMap::value_type & entry : node.Struct()) | ||||
| 		value.insert(entry.first, entry.second.convertTo<Type>()); | ||||
| } | ||||
|  | ||||
| template <typename Type> | ||||
| template<typename Type> | ||||
| void convert(std::set<Type> & value, const JsonNode & node) | ||||
| { | ||||
| 	value.clear(); | ||||
| @@ -205,7 +207,7 @@ void convert(std::set<Type> & value, const JsonNode & node) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| template <typename Type> | ||||
| template<typename Type> | ||||
| void convert(std::vector<Type> & value, const JsonNode & node) | ||||
| { | ||||
| 	value.clear(); | ||||
|   | ||||
| @@ -11,18 +11,18 @@ | ||||
| #include "StdInc.h" | ||||
| #include "JsonParser.h" | ||||
|  | ||||
| #include "JsonFormatException.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), | ||||
| 	lineCount(1), | ||||
| 	lineStart(0), | ||||
| 	pos(0) | ||||
| JsonParser::JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings) | ||||
| 	: input(inputString, stringSize) | ||||
| 	, settings(settings) | ||||
| 	, currentDepth(0) | ||||
| 	, lineCount(1) | ||||
| 	, lineStart(0) | ||||
| 	, pos(0) | ||||
| { | ||||
| } | ||||
|  | ||||
| @@ -30,24 +30,24 @@ JsonNode JsonParser::parse(const std::string & fileName) | ||||
| { | ||||
| 	JsonNode root; | ||||
|  | ||||
| 	if (input.empty()) | ||||
| 	if(input.empty()) | ||||
| 	{ | ||||
| 		error("File is empty", false); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if (!TextOperations::isValidUnicodeString(input.data(), input.size())) | ||||
| 		if(!TextOperations::isValidUnicodeString(input.data(), input.size())) | ||||
| 			error("Not a valid UTF-8 file", false); | ||||
|  | ||||
| 		extractValue(root); | ||||
| 		extractWhitespace(false); | ||||
|  | ||||
| 		//Warn if there are any non-whitespace symbols left | ||||
| 		if (pos < input.size()) | ||||
| 		if(pos < input.size()) | ||||
| 			error("Not all file was parsed!", true); | ||||
| 	} | ||||
|  | ||||
| 	if (!errors.empty()) | ||||
| 	if(!errors.empty()) | ||||
| 	{ | ||||
| 		logMod->warn("File %s is not a valid JSON file!", fileName); | ||||
| 		logMod->warn(errors); | ||||
| @@ -62,33 +62,40 @@ bool JsonParser::isValid() | ||||
|  | ||||
| bool JsonParser::extractSeparator() | ||||
| { | ||||
| 	if (!extractWhitespace()) | ||||
| 	if(!extractWhitespace()) | ||||
| 		return false; | ||||
|  | ||||
| 	if ( input[pos] !=':') | ||||
| 	if(input[pos] != ':') | ||||
| 		return error("Separator expected"); | ||||
|  | ||||
| 	pos++; | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractValue(JsonNode &node) | ||||
| bool JsonParser::extractValue(JsonNode & node) | ||||
| { | ||||
| 	if (!extractWhitespace()) | ||||
| 	if(!extractWhitespace()) | ||||
| 		return false; | ||||
|  | ||||
| 	switch (input[pos]) | ||||
| 	switch(input[pos]) | ||||
| 	{ | ||||
| 		case '\"': return extractString(node); | ||||
| 		case 'n' : return extractNull(node); | ||||
| 		case 't' : return extractTrue(node); | ||||
| 		case 'f' : return extractFalse(node); | ||||
| 		case '{' : return extractStruct(node); | ||||
| 		case '[' : return extractArray(node); | ||||
| 		case '-' : return extractFloat(node); | ||||
| 		case '\"': | ||||
| 			return extractString(node); | ||||
| 		case 'n': | ||||
| 			return extractNull(node); | ||||
| 		case 't': | ||||
| 			return extractTrue(node); | ||||
| 		case 'f': | ||||
| 			return extractFalse(node); | ||||
| 		case '{': | ||||
| 			return extractStruct(node); | ||||
| 		case '[': | ||||
| 			return extractArray(node); | ||||
| 		case '-': | ||||
| 			return extractFloat(node); | ||||
| 		default: | ||||
| 		{ | ||||
| 			if (input[pos] >= '0' && input[pos] <= '9') | ||||
| 			if(input[pos] >= '0' && input[pos] <= '9') | ||||
| 				return extractFloat(node); | ||||
| 			return error("Value expected!"); | ||||
| 		} | ||||
| @@ -100,73 +107,90 @@ bool JsonParser::extractWhitespace(bool verbose) | ||||
| 	//TODO: JSON5 - C-style multi-line comments | ||||
| 	//TODO: JSON5 - Additional white space characters are allowed | ||||
|  | ||||
| 	while (true) | ||||
| 	while(true) | ||||
| 	{ | ||||
| 		while(pos < input.size() && static_cast<ui8>(input[pos]) <= ' ') | ||||
| 		{ | ||||
| 			if (input[pos] == '\n') | ||||
| 			if(input[pos] == '\n') | ||||
| 			{ | ||||
| 				lineCount++; | ||||
| 				lineStart = pos+1; | ||||
| 				lineStart = pos + 1; | ||||
| 			} | ||||
| 			pos++; | ||||
| 		} | ||||
|  | ||||
| 		if (pos >= input.size() || input[pos] != '/') | ||||
| 		if(pos >= input.size() || input[pos] != '/') | ||||
| 			break; | ||||
|  | ||||
| 		if (settings.mode == JsonParsingSettings::JsonFormatMode::JSON) | ||||
| 		if(settings.mode == JsonParsingSettings::JsonFormatMode::JSON) | ||||
| 			error("Comments are not permitted in json!", true); | ||||
|  | ||||
| 		pos++; | ||||
| 		if (pos == input.size()) | ||||
| 		if(pos == input.size()) | ||||
| 			break; | ||||
| 		if (input[pos] == '/') | ||||
| 		if(input[pos] == '/') | ||||
| 			pos++; | ||||
| 		else | ||||
| 			error("Comments must consist of two slashes!", true); | ||||
|  | ||||
| 		while (pos < input.size() && input[pos] != '\n') | ||||
| 		while(pos < input.size() && input[pos] != '\n') | ||||
| 			pos++; | ||||
| 	} | ||||
|  | ||||
| 	if (pos >= input.size() && verbose) | ||||
| 	if(pos >= input.size() && verbose) | ||||
| 		return error("Unexpected end of file!"); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractEscaping(std::string &str) | ||||
| bool JsonParser::extractEscaping(std::string & str) | ||||
| { | ||||
| 	// TODO: support unicode escaping: | ||||
| 	// \u1234 | ||||
|  | ||||
| 	switch(input[pos]) | ||||
| 	{ | ||||
| 		break; case '\"': str += '\"'; | ||||
| 		break; case '\\': str += '\\'; | ||||
| 		break; case 'b': str += '\b'; | ||||
| 		break; case 'f': str += '\f'; | ||||
| 		break; case 'n': str += '\n'; | ||||
| 		break; case 'r': str += '\r'; | ||||
| 		break; case 't': str += '\t'; | ||||
| 		break; case '/': str += '/'; | ||||
| 		break; default: return error("Unknown escape sequence!", true); | ||||
| 		case '\"': | ||||
| 			str += '\"'; | ||||
| 			break; | ||||
| 		case '\\': | ||||
| 			str += '\\'; | ||||
| 			break; | ||||
| 		case 'b': | ||||
| 			str += '\b'; | ||||
| 			break; | ||||
| 		case 'f': | ||||
| 			str += '\f'; | ||||
| 			break; | ||||
| 		case 'n': | ||||
| 			str += '\n'; | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			str += '\r'; | ||||
| 			break; | ||||
| 		case 't': | ||||
| 			str += '\t'; | ||||
| 			break; | ||||
| 		case '/': | ||||
| 			str += '/'; | ||||
| 			break; | ||||
| 		default: | ||||
| 			return error("Unknown escape sequence!", true); | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractString(std::string &str) | ||||
| bool JsonParser::extractString(std::string & str) | ||||
| { | ||||
| 	//TODO: JSON5 - line breaks escaping | ||||
|  | ||||
| 	if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 	if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 	{ | ||||
| 		if (input[pos] != '\"') | ||||
| 		if(input[pos] != '\"') | ||||
| 			return error("String expected!"); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if (input[pos] != '\"' && input[pos] != '\'') | ||||
| 		if(input[pos] != '\"' && input[pos] != '\'') | ||||
| 			return error("String expected!"); | ||||
| 	} | ||||
|  | ||||
| @@ -175,32 +199,32 @@ bool JsonParser::extractString(std::string &str) | ||||
|  | ||||
| 	size_t first = pos; | ||||
|  | ||||
| 	while (pos != input.size()) | ||||
| 	while(pos != input.size()) | ||||
| 	{ | ||||
| 		if (input[pos] == lineTerminator) // Correct end of string | ||||
| 		if(input[pos] == lineTerminator) // Correct end of string | ||||
| 		{ | ||||
| 			str.append( &input[first], pos-first); | ||||
| 			str.append(&input[first], pos - first); | ||||
| 			pos++; | ||||
| 			return true; | ||||
| 		} | ||||
| 		if (input[pos] == '\\') // Escaping | ||||
| 		if(input[pos] == '\\') // Escaping | ||||
| 		{ | ||||
| 			str.append( &input[first], pos-first); | ||||
| 			str.append(&input[first], pos - first); | ||||
| 			pos++; | ||||
| 			if (pos == input.size()) | ||||
| 			if(pos == input.size()) | ||||
| 				break; | ||||
| 			extractEscaping(str); | ||||
| 			first = pos + 1; | ||||
| 		} | ||||
| 		if (input[pos] == '\n') // end-of-line | ||||
| 		if(input[pos] == '\n') // end-of-line | ||||
| 		{ | ||||
| 			str.append( &input[first], pos-first); | ||||
| 			str.append(&input[first], pos - first); | ||||
| 			return error("Closing quote not found!", true); | ||||
| 		} | ||||
| 		if(static_cast<unsigned char>(input[pos]) < ' ') // control character | ||||
| 		{ | ||||
| 			str.append( &input[first], pos-first); | ||||
| 			first = pos+1; | ||||
| 			str.append(&input[first], pos - first); | ||||
| 			first = pos + 1; | ||||
| 			error("Illegal character in the string!", true); | ||||
| 		} | ||||
| 		pos++; | ||||
| @@ -208,10 +232,10 @@ bool JsonParser::extractString(std::string &str) | ||||
| 	return error("Unterminated string!"); | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractString(JsonNode &node) | ||||
| bool JsonParser::extractString(JsonNode & node) | ||||
| { | ||||
| 	std::string str; | ||||
| 	if (!extractString(str)) | ||||
| 	if(!extractString(str)) | ||||
| 		return false; | ||||
|  | ||||
| 	node.setType(JsonNode::JsonType::DATA_STRING); | ||||
| @@ -221,13 +245,13 @@ bool JsonParser::extractString(JsonNode &node) | ||||
|  | ||||
| bool JsonParser::extractLiteral(std::string & literal) | ||||
| { | ||||
| 	while (pos < input.size() ) | ||||
| 	while(pos < input.size()) | ||||
| 	{ | ||||
| 		bool isUpperCase = input[pos]>='A' && input[pos]<='Z'; | ||||
| 		bool isLowerCase = input[pos]>='a' && input[pos]<='z'; | ||||
| 		bool isNumber = input[pos]>='0' && input[pos]<='9'; | ||||
| 		bool isUpperCase = input[pos] >= 'A' && input[pos] <= 'Z'; | ||||
| 		bool isLowerCase = input[pos] >= 'a' && input[pos] <= 'z'; | ||||
| 		bool isNumber = input[pos] >= '0' && input[pos] <= '9'; | ||||
|  | ||||
| 		if (!isUpperCase && !isLowerCase && !isNumber) | ||||
| 		if(!isUpperCase && !isLowerCase && !isNumber) | ||||
| 			break; | ||||
|  | ||||
| 		literal += input[pos]; | ||||
| @@ -238,13 +262,13 @@ bool JsonParser::extractLiteral(std::string & literal) | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractAndCompareLiteral(const std::string &expectedLiteral) | ||||
| bool JsonParser::extractAndCompareLiteral(const std::string & expectedLiteral) | ||||
| { | ||||
| 	std::string literal; | ||||
| 	if (!extractLiteral(literal)) | ||||
| 	if(!extractLiteral(literal)) | ||||
| 		return false; | ||||
|  | ||||
| 	if (literal != expectedLiteral) | ||||
| 	if(literal != expectedLiteral) | ||||
| 	{ | ||||
| 		return error("Expected " + expectedLiteral + ", but unknown literal found", true); | ||||
| 		return false; | ||||
| @@ -253,81 +277,81 @@ bool JsonParser::extractAndCompareLiteral(const std::string &expectedLiteral) | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractNull(JsonNode &node) | ||||
| bool JsonParser::extractNull(JsonNode & node) | ||||
| { | ||||
| 	if (!extractAndCompareLiteral("null")) | ||||
| 	if(!extractAndCompareLiteral("null")) | ||||
| 		return false; | ||||
|  | ||||
| 	node.clear(); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractTrue(JsonNode &node) | ||||
| bool JsonParser::extractTrue(JsonNode & node) | ||||
| { | ||||
| 	if (!extractAndCompareLiteral("true")) | ||||
| 	if(!extractAndCompareLiteral("true")) | ||||
| 		return false; | ||||
|  | ||||
| 	node.Bool() = true; | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractFalse(JsonNode &node) | ||||
| bool JsonParser::extractFalse(JsonNode & node) | ||||
| { | ||||
| 	if (!extractAndCompareLiteral("false")) | ||||
| 	if(!extractAndCompareLiteral("false")) | ||||
| 		return false; | ||||
|  | ||||
| 	node.Bool() = false; | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractStruct(JsonNode &node) | ||||
| bool JsonParser::extractStruct(JsonNode & node) | ||||
| { | ||||
| 	node.setType(JsonNode::JsonType::DATA_STRUCT); | ||||
|  | ||||
| 	if (currentDepth > settings.maxDepth) | ||||
| 	if(currentDepth > settings.maxDepth) | ||||
| 		error("Macimum allowed depth of json structure has been reached", true); | ||||
|  | ||||
| 	currentDepth++; | ||||
| 	pos++; | ||||
|  | ||||
| 	if (!extractWhitespace()) | ||||
| 	if(!extractWhitespace()) | ||||
| 		return false; | ||||
|  | ||||
| 	//Empty struct found | ||||
| 	if (input[pos] == '}') | ||||
| 	if(input[pos] == '}') | ||||
| 	{ | ||||
| 		pos++; | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	while (true) | ||||
| 	while(true) | ||||
| 	{ | ||||
| 		if (!extractWhitespace()) | ||||
| 		if(!extractWhitespace()) | ||||
| 			return false; | ||||
|  | ||||
| 		bool overrideFlag = false; | ||||
| 		std::string key; | ||||
|  | ||||
| 		if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 		if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 		{ | ||||
| 			if (!extractString(key)) | ||||
| 			if(!extractString(key)) | ||||
| 				return false; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (input[pos] == '\'' || input[pos] == '\"') | ||||
| 			if(input[pos] == '\'' || input[pos] == '\"') | ||||
| 			{ | ||||
| 				if (!extractString(key)) | ||||
| 				if(!extractString(key)) | ||||
| 					return false; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				if (!extractLiteral(key)) | ||||
| 				if(!extractLiteral(key)) | ||||
| 					return false; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (key.find('#') != std::string::npos) | ||||
| 		if(key.find('#') != std::string::npos) | ||||
| 		{ | ||||
| 			// split key string into actual key and meta-flags | ||||
| 			std::vector<std::string> keyAndFlags; | ||||
| @@ -337,25 +361,25 @@ bool JsonParser::extractStruct(JsonNode &node) | ||||
|  | ||||
| 			for(int i = 1; i < keyAndFlags.size(); i++) | ||||
| 			{ | ||||
| 				if (keyAndFlags[i] == "override") | ||||
| 				if(keyAndFlags[i] == "override") | ||||
| 					overrideFlag = true; | ||||
| 				else | ||||
| 					error("Encountered unknown flag #" + keyAndFlags[i], true); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (node.Struct().find(key) != node.Struct().end()) | ||||
| 		if(node.Struct().find(key) != node.Struct().end()) | ||||
| 			error("Duplicate element encountered!", true); | ||||
|  | ||||
| 		if (!extractSeparator()) | ||||
| 		if(!extractSeparator()) | ||||
| 			return false; | ||||
|  | ||||
| 		if (!extractElement(node.Struct()[key], '}')) | ||||
| 		if(!extractElement(node.Struct()[key], '}')) | ||||
| 			return false; | ||||
|  | ||||
| 		node.Struct()[key].setOverrideFlag(overrideFlag); | ||||
|  | ||||
| 		if (input[pos] == '}') | ||||
| 		if(input[pos] == '}') | ||||
| 		{ | ||||
| 			pos++; | ||||
| 			return true; | ||||
| @@ -363,35 +387,35 @@ bool JsonParser::extractStruct(JsonNode &node) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractArray(JsonNode &node) | ||||
| bool JsonParser::extractArray(JsonNode & node) | ||||
| { | ||||
| 	if (currentDepth > settings.maxDepth) | ||||
| 	if(currentDepth > settings.maxDepth) | ||||
| 		error("Macimum allowed depth of json structure has been reached", true); | ||||
|  | ||||
| 	currentDepth++; | ||||
| 	pos++; | ||||
| 	node.setType(JsonNode::JsonType::DATA_VECTOR); | ||||
|  | ||||
| 	if (!extractWhitespace()) | ||||
| 	if(!extractWhitespace()) | ||||
| 		return false; | ||||
|  | ||||
| 	//Empty array found | ||||
| 	if (input[pos] == ']') | ||||
| 	if(input[pos] == ']') | ||||
| 	{ | ||||
| 		pos++; | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	while (true) | ||||
| 	while(true) | ||||
| 	{ | ||||
| 		//NOTE: currently 50% of time is this vector resizing. | ||||
| 		//May be useful to use list during parsing and then swap() all items to vector | ||||
| 		node.Vector().resize(node.Vector().size()+1); | ||||
| 		node.Vector().resize(node.Vector().size() + 1); | ||||
|  | ||||
| 		if (!extractElement(node.Vector().back(), ']')) | ||||
| 		if(!extractElement(node.Vector().back(), ']')) | ||||
| 			return false; | ||||
|  | ||||
| 		if (input[pos] == ']') | ||||
| 		if(input[pos] == ']') | ||||
| 		{ | ||||
| 			pos++; | ||||
| 			return true; | ||||
| @@ -399,92 +423,92 @@ bool JsonParser::extractArray(JsonNode &node) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractElement(JsonNode &node, char terminator) | ||||
| bool JsonParser::extractElement(JsonNode & node, char terminator) | ||||
| { | ||||
| 	if (!extractValue(node)) | ||||
| 	if(!extractValue(node)) | ||||
| 		return false; | ||||
|  | ||||
| 	if (!extractWhitespace()) | ||||
| 	if(!extractWhitespace()) | ||||
| 		return false; | ||||
|  | ||||
| 	bool comma = (input[pos] == ','); | ||||
| 	if (comma ) | ||||
| 	if(comma) | ||||
| 	{ | ||||
| 		pos++; | ||||
| 		if (!extractWhitespace()) | ||||
| 		if(!extractWhitespace()) | ||||
| 			return false; | ||||
| 	} | ||||
|  | ||||
| 	if (input[pos] == terminator) | ||||
| 	if(input[pos] == terminator) | ||||
| 	{ | ||||
| 		if (comma) | ||||
| 		if(comma) | ||||
| 		{ | ||||
| 			if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 			if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 				error("Extra comma found!", true); | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	if (!comma) | ||||
| 	if(!comma) | ||||
| 		error("Comma expected!", true); | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::extractFloat(JsonNode &node) | ||||
| bool JsonParser::extractFloat(JsonNode & node) | ||||
| { | ||||
| 	//TODO: JSON5 - hexacedimal support | ||||
| 	//TODO: JSON5 - Numbers may be IEEE 754 positive infinity, negative infinity, and NaN (why?) | ||||
|  | ||||
| 	assert(input[pos] == '-' || (input[pos] >= '0' && input[pos] <= '9')); | ||||
| 	bool negative=false; | ||||
| 	double result=0; | ||||
| 	bool negative = false; | ||||
| 	double result = 0; | ||||
| 	si64 integerPart = 0; | ||||
| 	bool isFloat = false; | ||||
|  | ||||
| 	if (input[pos] == '+') | ||||
| 	if(input[pos] == '+') | ||||
| 	{ | ||||
| 		if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 		if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 			error("Positive numbers should not have plus sign!", true); | ||||
| 		pos++; | ||||
| 	} | ||||
| 	else if (input[pos] == '-') | ||||
| 	else if(input[pos] == '-') | ||||
| 	{ | ||||
| 		pos++; | ||||
| 		negative = true; | ||||
| 	} | ||||
|  | ||||
| 	if (input[pos] < '0' || input[pos] > '9') | ||||
| 	if(input[pos] < '0' || input[pos] > '9') | ||||
| 	{ | ||||
| 		if (input[pos] != '.'  && settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 		if(input[pos] != '.' && settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 			return error("Number expected!"); | ||||
| 	} | ||||
|  | ||||
| 	//Extract integer part | ||||
| 	while (input[pos] >= '0' && input[pos] <= '9') | ||||
| 	while(input[pos] >= '0' && input[pos] <= '9') | ||||
| 	{ | ||||
| 		integerPart = integerPart*10+(input[pos]-'0'); | ||||
| 		integerPart = integerPart * 10 + (input[pos] - '0'); | ||||
| 		pos++; | ||||
| 	} | ||||
|  | ||||
| 	result = static_cast<double>(integerPart); | ||||
|  | ||||
| 	if (input[pos] == '.') | ||||
| 	if(input[pos] == '.') | ||||
| 	{ | ||||
| 		//extract fractional part | ||||
| 		isFloat = true; | ||||
| 		pos++; | ||||
| 		double fractMult = 0.1; | ||||
|  | ||||
| 		if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 		if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5) | ||||
| 		{ | ||||
| 			if (input[pos] < '0' || input[pos] > '9') | ||||
| 			if(input[pos] < '0' || input[pos] > '9') | ||||
| 				return error("Decimal part expected!"); | ||||
| 		} | ||||
|  | ||||
| 		while (input[pos] >= '0' && input[pos] <= '9') | ||||
| 		while(input[pos] >= '0' && input[pos] <= '9') | ||||
| 		{ | ||||
| 			result = result + fractMult*(input[pos]-'0'); | ||||
| 			result = result + fractMult * (input[pos] - '0'); | ||||
| 			fractMult /= 10; | ||||
| 			pos++; | ||||
| 		} | ||||
| @@ -508,12 +532,12 @@ bool JsonParser::extractFloat(JsonNode &node) | ||||
| 			pos++; | ||||
| 		} | ||||
|  | ||||
| 		if (input[pos] < '0' || input[pos] > '9') | ||||
| 		if(input[pos] < '0' || input[pos] > '9') | ||||
| 			return error("Exponential part expected!"); | ||||
|  | ||||
| 		while (input[pos] >= '0' && input[pos] <= '9') | ||||
| 		while(input[pos] >= '0' && input[pos] <= '9') | ||||
| 		{ | ||||
| 			power = power*10 + (input[pos]-'0'); | ||||
| 			power = power * 10 + (input[pos] - '0'); | ||||
| 			pos++; | ||||
| 		} | ||||
|  | ||||
| @@ -543,16 +567,15 @@ bool JsonParser::extractFloat(JsonNode &node) | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool JsonParser::error(const std::string &message, bool warning) | ||||
| bool JsonParser::error(const std::string & message, bool warning) | ||||
| { | ||||
| 	if (settings.strict) | ||||
| 	if(settings.strict) | ||||
| 		throw JsonFormatException(message); | ||||
|  | ||||
| 	std::ostringstream stream; | ||||
| 	std::string type(warning?" warning: ":" error: "); | ||||
| 	std::string type(warning ? " warning: " : " error: "); | ||||
|  | ||||
| 	stream << "At line " << lineCount << ", position "<<pos-lineStart | ||||
| 		   << type << message <<"\n"; | ||||
| 	stream << "At line " << lineCount << ", position " << pos - lineStart << type << message << "\n"; | ||||
| 	errors += stream.str(); | ||||
|  | ||||
| 	return warning; | ||||
|   | ||||
| @@ -18,34 +18,34 @@ class JsonParser | ||||
| { | ||||
| 	const JsonParsingSettings settings; | ||||
|  | ||||
| 	std::string errors;     // Contains description of all encountered errors | ||||
| 	std::string_view input;      // Input data | ||||
| 	std::string errors; // Contains description of all encountered errors | ||||
| 	std::string_view input; // Input data | ||||
| 	uint32_t lineCount; // Currently parsed line, starting from 1 | ||||
| 	uint32_t currentDepth; | ||||
| 	size_t lineStart;       // Position of current line start | ||||
| 	size_t pos;             // Current position of parser | ||||
| 	size_t lineStart; // Position of current line start | ||||
| 	size_t pos; // Current position of parser | ||||
|  | ||||
| 	//Helpers | ||||
| 	bool extractEscaping(std::string &str); | ||||
| 	bool extractLiteral(std::string &literal); | ||||
| 	bool extractAndCompareLiteral(const std::string &expectedLiteral); | ||||
| 	bool extractString(std::string &string); | ||||
| 	bool extractEscaping(std::string & str); | ||||
| 	bool extractLiteral(std::string & literal); | ||||
| 	bool extractAndCompareLiteral(const std::string & expectedLiteral); | ||||
| 	bool extractString(std::string & string); | ||||
| 	bool extractWhitespace(bool verbose = true); | ||||
| 	bool extractSeparator(); | ||||
| 	bool extractElement(JsonNode &node, char terminator); | ||||
| 	bool extractElement(JsonNode & node, char terminator); | ||||
|  | ||||
| 	//Methods for extracting JSON data | ||||
| 	bool extractArray(JsonNode &node); | ||||
| 	bool extractFalse(JsonNode &node); | ||||
| 	bool extractFloat(JsonNode &node); | ||||
| 	bool extractNull(JsonNode &node); | ||||
| 	bool extractString(JsonNode &node); | ||||
| 	bool extractStruct(JsonNode &node); | ||||
| 	bool extractTrue(JsonNode &node); | ||||
| 	bool extractValue(JsonNode &node); | ||||
| 	bool extractArray(JsonNode & node); | ||||
| 	bool extractFalse(JsonNode & node); | ||||
| 	bool extractFloat(JsonNode & node); | ||||
| 	bool extractNull(JsonNode & node); | ||||
| 	bool extractString(JsonNode & node); | ||||
| 	bool extractStruct(JsonNode & node); | ||||
| 	bool extractTrue(JsonNode & node); | ||||
| 	bool extractValue(JsonNode & node); | ||||
|  | ||||
| 	//Add error\warning message to list | ||||
| 	bool error(const std::string &message, bool warning=false); | ||||
| 	bool error(const std::string & message, bool warning = false); | ||||
|  | ||||
| public: | ||||
| 	JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings); | ||||
|   | ||||
| @@ -9,9 +9,9 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "GameCallbackHolder.h" | ||||
| #include "GameConstants.h" | ||||
| #include "ResourceSet.h" | ||||
| #include "GameCallbackHolder.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
|   | ||||
| @@ -16,28 +16,28 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
| template<typename Iterator> | ||||
| void JsonWriter::writeContainer(Iterator begin, Iterator end) | ||||
| { | ||||
| 	if (begin == end) | ||||
| 	if(begin == end) | ||||
| 		return; | ||||
|  | ||||
| 	prefix += '\t'; | ||||
|  | ||||
| 	writeEntry(begin++); | ||||
|  | ||||
| 	while (begin != end) | ||||
| 	while(begin != end) | ||||
| 	{ | ||||
| 		out << (compactMode ? ", " : ",\n"); | ||||
| 		writeEntry(begin++); | ||||
| 	} | ||||
|  | ||||
| 	out << (compactMode ? "" : "\n"); | ||||
| 	prefix.resize(prefix.size()-1); | ||||
| 	prefix.resize(prefix.size() - 1); | ||||
| } | ||||
|  | ||||
| void JsonWriter::writeEntry(JsonMap::const_iterator entry) | ||||
| { | ||||
| 	if(!compactMode) | ||||
| 	{ | ||||
| 		if (!entry->second.getModScope().empty()) | ||||
| 		if(!entry->second.getModScope().empty()) | ||||
| 			out << prefix << " // " << entry->second.getModScope() << "\n"; | ||||
| 		out << prefix; | ||||
| 	} | ||||
| @@ -50,27 +50,25 @@ void JsonWriter::writeEntry(JsonVector::const_iterator entry) | ||||
| { | ||||
| 	if(!compactMode) | ||||
| 	{ | ||||
| 		if (!entry->getModScope().empty()) | ||||
| 		if(!entry->getModScope().empty()) | ||||
| 			out << prefix << " // " << entry->getModScope() << "\n"; | ||||
| 		out << prefix; | ||||
| 	} | ||||
| 	writeNode(*entry); | ||||
| } | ||||
|  | ||||
| void JsonWriter::writeString(const std::string &string) | ||||
| 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'}; | ||||
|  | ||||
| 	out <<'\"'; | ||||
| 	out << '\"'; | ||||
| 	size_t pos = 0; | ||||
| 	size_t start = 0; | ||||
| 	for (; pos<string.size(); pos++) | ||||
| 	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(escaped_code.begin(), escaped_code.end(), string[pos + 1]) != escaped_code.end())) | ||||
| 		{ | ||||
| 			pos++; //write unchanged, next simbol also checked | ||||
| 		} | ||||
| @@ -78,20 +76,19 @@ void JsonWriter::writeString(const std::string &string) | ||||
| 		{ | ||||
| 			size_t escapedPos = escaped.find(string[pos]); | ||||
|  | ||||
| 			if (escapedPos != std::string::npos) | ||||
| 			if(escapedPos != std::string::npos) | ||||
| 			{ | ||||
| 				out.write(string.data()+start, pos - start); | ||||
| 				out.write(string.data() + start, pos - start); | ||||
| 				out << '\\' << escaped_code[escapedPos]; | ||||
| 				start = pos+1; | ||||
| 				start = pos + 1; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| 	out.write(string.data()+start, pos - start); | ||||
| 	out <<'\"'; | ||||
| 	out.write(string.data() + start, pos - start); | ||||
| 	out << '\"'; | ||||
| } | ||||
|  | ||||
| void JsonWriter::writeNode(const JsonNode &node) | ||||
| void JsonWriter::writeNode(const JsonNode & node) | ||||
| { | ||||
| 	bool originalMode = compactMode; | ||||
| 	if(compact && !compactMode && node.isCompact()) | ||||
| @@ -99,40 +96,48 @@ void JsonWriter::writeNode(const JsonNode &node) | ||||
|  | ||||
| 	switch(node.getType()) | ||||
| 	{ | ||||
| 		break; case JsonNode::JsonType::DATA_NULL: | ||||
| 		case JsonNode::JsonType::DATA_NULL: | ||||
| 			out << "null"; | ||||
| 			break; | ||||
|  | ||||
| 		break; case JsonNode::JsonType::DATA_BOOL: | ||||
| 			if (node.Bool()) | ||||
| 		case JsonNode::JsonType::DATA_BOOL: | ||||
| 			if(node.Bool()) | ||||
| 				out << "true"; | ||||
| 			else | ||||
| 				out << "false"; | ||||
| 			break; | ||||
|  | ||||
| 		break; case JsonNode::JsonType::DATA_FLOAT: | ||||
| 		case JsonNode::JsonType::DATA_FLOAT: | ||||
| 			out << node.Float(); | ||||
| 			break; | ||||
|  | ||||
| 		break; case JsonNode::JsonType::DATA_STRING: | ||||
| 		case JsonNode::JsonType::DATA_STRING: | ||||
| 			writeString(node.String()); | ||||
| 			break; | ||||
|  | ||||
| 		break; case JsonNode::JsonType::DATA_VECTOR: | ||||
| 		case JsonNode::JsonType::DATA_VECTOR: | ||||
| 			out << "[" << (compactMode ? " " : "\n"); | ||||
| 			writeContainer(node.Vector().begin(), node.Vector().end()); | ||||
| 			out << (compactMode ? " " : prefix) << "]"; | ||||
| 			break; | ||||
|  | ||||
| 		break; case JsonNode::JsonType::DATA_STRUCT: | ||||
| 		case JsonNode::JsonType::DATA_STRUCT: | ||||
| 			out << "{" << (compactMode ? " " : "\n"); | ||||
| 			writeContainer(node.Struct().begin(), node.Struct().end()); | ||||
| 			out << (compactMode ? " " : prefix) << "}"; | ||||
| 			break; | ||||
|  | ||||
| 		break; case JsonNode::JsonType::DATA_INTEGER: | ||||
| 		case JsonNode::JsonType::DATA_INTEGER: | ||||
| 			out << node.Integer(); | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	compactMode = originalMode; | ||||
| } | ||||
|  | ||||
| JsonWriter::JsonWriter(std::ostream & output, bool compact) | ||||
| 	: out(output), compact(compact) | ||||
| 	: out(output) | ||||
| 	, compact(compact) | ||||
| { | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -22,6 +22,7 @@ class JsonWriter | ||||
| 	bool compact; | ||||
| 	//tracks whether we are currently using single-line format | ||||
| 	bool compactMode = false; | ||||
|  | ||||
| public: | ||||
| 	template<typename Iterator> | ||||
| 	void writeContainer(Iterator begin, Iterator end); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user