浏览代码

Advance Logical identifier condition

AlexVinS 9 年之前
父节点
当前提交
17e557be17

+ 11 - 1
lib/mapObjects/CGTownInstance.cpp

@@ -1123,10 +1123,20 @@ void CGTownInstance::battleFinished(const CGHeroInstance *hero, const BattleResu
 	}
 }
 
-void CGTownInstance::serializeJsonOptions(JsonSerializeFormat& handler)
+void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler)
 {
 	CGObjectInstance::serializeJsonOwner(handler);
 	CCreatureSet::serializeJson(handler, "army");
+	handler.serializeBool<ui8>("tightFormation", 1, 0, formation);
+	handler.serializeString("name", name);
+
+
+
+	if(!handler.saving)
+	{
+		builtBuildings.insert(BuildingID::DEFAULT);//just in case
+	}
+
 
 	//todo: CGTownInstance::serializeJsonOptions
 }

+ 1 - 1
lib/mapping/MapFormatJson.cpp

@@ -235,7 +235,7 @@ void CMapFormatJson::serializePlayerInfo(JsonSerializeFormat & handler)
 
 		serializeAllowedFactions(handler, info.allowedFactions);
 
-		handler.serializeBoolEnum("canPlay", "PlayerOrAI", "AIOnly", info.canHumanPlay);
+		handler.serializeEnum("canPlay", "PlayerOrAI", "AIOnly", info.canHumanPlay);
 
 		//mainTown
 		if(handler.saving)

+ 51 - 29
lib/serializer/JsonDeserializer.cpp

@@ -25,7 +25,7 @@ void JsonDeserializer::serializeBool(const std::string & fieldName, bool & value
 	value = current->operator[](fieldName).Bool();
 }
 
-void JsonDeserializer::serializeBoolEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value)
+void JsonDeserializer::serializeEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value)
 {
 	const JsonNode & tmp = current->operator[](fieldName);
 
@@ -72,32 +72,11 @@ void JsonDeserializer::serializeLIC(const std::string & fieldName, const TDecode
 	if(field.isNull())
 		return;
 
-	auto loadPart = [&](const JsonVector & part, const bool val)
-	{
-		for(size_t index = 0; index < part.size(); index++)
-		{
-			const std::string & identifier = part[index].String();
-
-			si32 rawId = decoder(identifier);
-			if(rawId >= 0)
-			{
-				if(rawId < value.size())
-					value[rawId] = val;
-				else
-					logGlobal->errorStream() << "JsonDeserializer::serializeLIC: " << fieldName <<" id out of bounds " << rawId;
-			}
-			else
-			{
-				logGlobal->errorStream() << "JsonDeserializer::serializeLIC: " << fieldName <<" identifier not resolved " << identifier;
-			}
-		}
-	};
+	const JsonNode & anyOf = field["anyOf"];
+	const JsonNode & allOf = field["allOf"];
+	const JsonNode & noneOf = field["noneOf"];
 
-	const JsonVector & anyOf = field["anyOf"].Vector();
-	const JsonVector & allOf = field["allOf"].Vector();
-	const JsonVector & noneOf = field["noneOf"].Vector();
-
-	if(anyOf.empty() && allOf.empty())
+	if(anyOf.Vector().empty() && allOf.Vector().empty())
 	{
 		//permissive mode
 		value = standard;
@@ -108,11 +87,37 @@ void JsonDeserializer::serializeLIC(const std::string & fieldName, const TDecode
 		value.clear();
 		value.resize(standard.size(), false);
 
-		loadPart(anyOf, true);
-		loadPart(allOf, true);
+		readLICPart(anyOf, decoder, true, value);
+		readLICPart(allOf, decoder, true, value);
 	}
 
-	loadPart(noneOf, false);
+	readLICPart(noneOf, decoder, false, value);
+}
+
+void JsonDeserializer::serializeLIC(const std::string & fieldName, LIC & value)
+{
+	const JsonNode & field = current->operator[](fieldName);
+
+	const JsonNode & anyOf = field["anyOf"];
+	const JsonNode & allOf = field["allOf"];
+	const JsonNode & noneOf = field["noneOf"];
+
+	if(anyOf.Vector().empty())
+	{
+		//permissive mode
+		value.any = value.standard;
+	}
+	else
+	{
+		//restrictive mode
+		value.any.clear();
+		value.any.resize(value.standard.size(), false);
+
+		readLICPart(anyOf, value.decoder, true, value.any);
+	}
+
+	readLICPart(allOf, value.decoder, true, value.all);
+	readLICPart(noneOf, value.decoder, true, value.none);
 }
 
 void JsonDeserializer::serializeString(const std::string & fieldName, std::string & value)
@@ -120,3 +125,20 @@ void JsonDeserializer::serializeString(const std::string & fieldName, std::strin
 	value = current->operator[](fieldName).String();
 }
 
+void JsonDeserializer::readLICPart(const JsonNode & part, const TDecoder & decoder, const bool val, std::vector<bool> & value)
+{
+	for(size_t index = 0; index < part.Vector().size(); index++)
+	{
+		const std::string & identifier = part.Vector()[index].String();
+
+		const si32 rawId = decoder(identifier);
+		if(rawId >= 0)
+		{
+			if(rawId < value.size())
+				value[rawId] = val;
+			else
+				logGlobal->errorStream() << "JsonDeserializer::serializeLIC: id out of bounds " << rawId;
+		}
+	}
+}
+

+ 4 - 1
lib/serializer/JsonDeserializer.h

@@ -20,12 +20,15 @@ public:
 	JsonDeserializer(JsonNode & root_);
 
 	void serializeBool(const std::string & fieldName, bool & value) override;
-	void serializeBoolEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value) override;
+	void serializeEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value) override;
 	void serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value) override;
+	void serializeLIC(const std::string & fieldName, LIC & value) override;
 	void serializeString(const std::string & fieldName, std::string & value) override;
 
 protected:
 	void serializeFloat(const std::string & fieldName, double & value) override;
 	void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) override;
 	void serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) override;
+private:
+	void readLICPart(const JsonNode & part, const TDecoder & decoder, const bool val, std::vector<bool> & value);
 };

+ 9 - 1
lib/serializer/JsonSerializeFormat.cpp

@@ -14,6 +14,7 @@
 
 #include "../JsonNode.h"
 
+
 //JsonStructSerializer
 JsonStructSerializer::JsonStructSerializer(JsonStructSerializer&& other):
 	restoreState(false),
@@ -48,7 +49,6 @@ JsonStructSerializer::JsonStructSerializer(JsonStructSerializer & parent, const
 	owner.current = thisNode;
 }
 
-
 JsonStructSerializer JsonStructSerializer::enterStruct(const std::string & fieldName)
 {
 	return JsonStructSerializer(*this, fieldName);
@@ -64,6 +64,14 @@ JsonSerializeFormat * JsonStructSerializer::operator->()
 	return &owner;
 }
 
+JsonSerializeFormat::LIC::LIC(const std::vector<bool> & Standard, const TDecoder & Decoder, const TEncoder & Encoder):
+	standard(Standard), decoder(Decoder), encoder(Encoder)
+{
+	any = standard;
+	all.resize(standard.size(), false);
+	none.resize(standard.size(), false);
+}
+
 
 //JsonSerializeFormat
 JsonSerializeFormat::JsonSerializeFormat(JsonNode & root_, const bool saving_):

+ 25 - 2
lib/serializer/JsonSerializeFormat.h

@@ -47,6 +47,16 @@ public:
 	///may assume that object index is valid
 	typedef std::function<std::string(si32)> TEncoder;
 
+	struct LIC
+	{
+		LIC(const std::vector<bool> & Standard, const TDecoder & Decoder, const TEncoder & Encoder);
+
+		const std::vector<bool> & standard;
+		const TDecoder & decoder;
+		const TEncoder & encoder;
+		std::vector<bool> all, any, none;
+	};
+
 	const bool saving;
 
 	JsonSerializeFormat() = delete;
@@ -64,10 +74,20 @@ public:
 
 	JsonStructSerializer enterStruct(const std::string & fieldName);
 
+	template <typename T>
+	void serializeBool(const std::string & fieldName, const T trueValue, const T falseValue, T & value)
+	{
+		bool temp = (value == trueValue);
+		serializeBool(fieldName, temp);
+		if(!saving)
+			value = temp ? trueValue : falseValue;
+	}
+
 	virtual void serializeBool(const std::string & fieldName, bool & value) = 0;
-	virtual void serializeBoolEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value) = 0;
 
-	/** @brief Restrictive serialization of Logical identifier condition (only "anyOf" used), full deserialization
+	virtual void serializeEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value) = 0;
+
+	/** @brief Restrictive ("anyOf") simple serialization of Logical identifier condition, simple deserialization (allOf=anyOf)
 	 *
 	 * @param fieldName
 	 * @param decoder resolve callback, should report errors itself and do not throw
@@ -77,6 +97,9 @@ public:
 	 */
 	virtual void serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value) = 0;
 
+	/** @brief Complete serialization of Logical identifier condition
+	 */
+	virtual void serializeLIC(const std::string & fieldName, LIC & value) = 0;
 
 	template <typename T>
 	void serializeNumericEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const T defaultValue, T & value)

+ 26 - 9
lib/serializer/JsonSerializer.cpp

@@ -26,7 +26,7 @@ void JsonSerializer::serializeBool(const std::string & fieldName, bool & value)
 		current->operator[](fieldName).Bool() = true;
 }
 
-void JsonSerializer::serializeBoolEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value)
+void JsonSerializer::serializeEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value)
 {
 	current->operator[](fieldName).String() = value ? trueValue : falseValue;
 }
@@ -57,16 +57,19 @@ void JsonSerializer::serializeLIC(const std::string & fieldName, const TDecoder
 	assert(standard.size() == value.size());
 	if(standard == value)
 		return;
-	auto & target = current->operator[](fieldName)["anyOf"].Vector();
-	for(si32 idx = 0; idx < value.size(); idx ++)
+
+	writeLICPart(fieldName, "anyOf", encoder, value);
+}
+
+void JsonSerializer::serializeLIC(const std::string & fieldName, LIC & value)
+{
+	if(value.any != value.standard)
 	{
-		if(value[idx])
-		{
-			JsonNode val(JsonNode::DATA_STRING);
-			val.String() = encoder(idx);
-			target.push_back(std::move(val));
-		}
+		writeLICPart(fieldName, "anyOf", value.encoder, value.any);
 	}
+
+	writeLICPart(fieldName, "allOf", value.encoder, value.all);
+	writeLICPart(fieldName, "noneOf", value.encoder, value.none);
 }
 
 void JsonSerializer::serializeString(const std::string & fieldName, std::string & value)
@@ -75,3 +78,17 @@ void JsonSerializer::serializeString(const std::string & fieldName, std::string
 		current->operator[](fieldName).String() = value;
 }
 
+void JsonSerializer::writeLICPart(const std::string& fieldName, const std::string& partName, const TEncoder& encoder, const std::vector<bool> & data)
+{
+	auto & target = current->operator[](fieldName)[partName].Vector();
+	for(si32 idx = 0; idx < data.size(); idx ++)
+	{
+		if(data[idx])
+		{
+			JsonNode val(JsonNode::DATA_STRING);
+			val.String() = encoder(idx);
+			target.push_back(std::move(val));
+		}
+	}
+}
+

+ 5 - 1
lib/serializer/JsonSerializer.h

@@ -20,12 +20,16 @@ public:
 	JsonSerializer(JsonNode & root_);
 
 	void serializeBool(const std::string & fieldName, bool & value) override;
-	void serializeBoolEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value) override;
+	void serializeEnum(const std::string & fieldName, const std::string & trueValue, const std::string & falseValue, bool & value) override;
 	void serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value) override;
+	void serializeLIC(const std::string & fieldName, LIC & value) override;
 	void serializeString(const std::string & fieldName, std::string & value) override;
 
 protected:
 	void serializeFloat(const std::string & fieldName, double & value) override;
 	void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) override;
 	void serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) override;
+
+private:
+	void writeLICPart(const std::string & fieldName, const std::string & partName, const TEncoder & encoder, const std::vector<bool> & data);
 };