diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 808416670..b16306be1 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/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("tightFormation", 1, 0, formation); + handler.serializeString("name", name); + + + + if(!handler.saving) + { + builtBuildings.insert(BuildingID::DEFAULT);//just in case + } + //todo: CGTownInstance::serializeJsonOptions } diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index e35222493..9b33d2b52 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/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) diff --git a/lib/serializer/JsonDeserializer.cpp b/lib/serializer/JsonDeserializer.cpp index 72af19bb0..53cd0afaa 100644 --- a/lib/serializer/JsonDeserializer.cpp +++ b/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(); + const JsonNode & anyOf = field["anyOf"]; + const JsonNode & allOf = field["allOf"]; + const JsonNode & noneOf = field["noneOf"]; - 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 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 & 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; + } + } +} + diff --git a/lib/serializer/JsonDeserializer.h b/lib/serializer/JsonDeserializer.h index 2130b3812..cfd7031a5 100644 --- a/lib/serializer/JsonDeserializer.h +++ b/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 & standard, std::vector & 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 & 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 & value); }; diff --git a/lib/serializer/JsonSerializeFormat.cpp b/lib/serializer/JsonSerializeFormat.cpp index 11b4f947d..f960a8126 100644 --- a/lib/serializer/JsonSerializeFormat.cpp +++ b/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 & 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_): diff --git a/lib/serializer/JsonSerializeFormat.h b/lib/serializer/JsonSerializeFormat.h index 424f2d9aa..70ab8abcb 100644 --- a/lib/serializer/JsonSerializeFormat.h +++ b/lib/serializer/JsonSerializeFormat.h @@ -47,6 +47,16 @@ public: ///may assume that object index is valid typedef std::function TEncoder; + struct LIC + { + LIC(const std::vector & Standard, const TDecoder & Decoder, const TEncoder & Encoder); + + const std::vector & standard; + const TDecoder & decoder; + const TEncoder & encoder; + std::vector all, any, none; + }; + const bool saving; JsonSerializeFormat() = delete; @@ -64,10 +74,20 @@ public: JsonStructSerializer enterStruct(const std::string & fieldName); - 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; + template + 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; + } - /** @brief Restrictive serialization of Logical identifier condition (only "anyOf" used), full deserialization + virtual void serializeBool(const std::string & fieldName, bool & value) = 0; + + 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 & standard, std::vector & value) = 0; + /** @brief Complete serialization of Logical identifier condition + */ + virtual void serializeLIC(const std::string & fieldName, LIC & value) = 0; template void serializeNumericEnum(const std::string & fieldName, const std::vector & enumMap, const T defaultValue, T & value) diff --git a/lib/serializer/JsonSerializer.cpp b/lib/serializer/JsonSerializer.cpp index 8f4d37640..22f4215e2 100644 --- a/lib/serializer/JsonSerializer.cpp +++ b/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 & 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)); + } + } +} + diff --git a/lib/serializer/JsonSerializer.h b/lib/serializer/JsonSerializer.h index ad19fe782..1fae5fb67 100644 --- a/lib/serializer/JsonSerializer.h +++ b/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 & standard, std::vector & 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 & 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 & data); };