1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Configure JSON merge behaviour via #override flag (#423)

* added json flags; override flag affects how structs are merged
This commit is contained in:
Henning Koehler 2018-03-05 16:30:10 +13:00 committed by ArseniyShestakov
parent f126a34a5e
commit 4ee9d7f65a
4 changed files with 47 additions and 12 deletions

View File

@ -46,6 +46,8 @@ void JsonWriter::writeEntry(JsonMap::const_iterator entry)
{
if (!entry->second.meta.empty())
out << prefix << " // " << entry->second.meta << "\n";
if(!entry->second.flags.empty())
out << prefix << " // flags: " << boost::algorithm::join(entry->second.flags, ", ") << "\n";
out << prefix;
}
writeString(entry->first);
@ -59,6 +61,8 @@ void JsonWriter::writeEntry(JsonVector::const_iterator entry)
{
if (!entry->meta.empty())
out << prefix << " // " << entry->meta << "\n";
if(!entry->flags.empty())
out << prefix << " // flags: " << boost::algorithm::join(entry->flags, ", ") << "\n";
out << prefix;
}
writeNode(*entry);
@ -389,6 +393,18 @@ bool JsonParser::extractStruct(JsonNode &node)
if (!extractString(key))
return false;
// split key string into actual key and meta-flags
std::vector<std::string> keyAndFlags;
boost::split(keyAndFlags, key, boost::is_any_of("#"));
key = keyAndFlags[0];
// check for unknown flags - helps with debugging
std::vector<std::string> knownFlags = { "override" };
for(int i = 1; i < keyAndFlags.size(); i++)
{
if(!vstd::contains(knownFlags, keyAndFlags[i]))
error("Encountered unknown flag #" + keyAndFlags[i], true);
}
if (node.Struct().find(key) != node.Struct().end())
error("Dublicated element encountered!", true);
@ -398,6 +414,10 @@ bool JsonParser::extractStruct(JsonNode &node)
if (!extractElement(node.Struct()[key], '}'))
return false;
// flags from key string belong to referenced element
for(int i = 1; i < keyAndFlags.size(); i++)
node.Struct()[key].flags.push_back(keyAndFlags[i]);
if (input[pos] == '}')
{
pos++;

View File

@ -70,7 +70,8 @@ JsonNode::JsonNode(ResourceID && fileURI, bool &isValidSyntax):
JsonNode::JsonNode(const JsonNode &copy):
type(JsonType::DATA_NULL),
meta(copy.meta)
meta(copy.meta),
flags(copy.flags)
{
setType(copy.getType());
switch(type)
@ -96,6 +97,7 @@ void JsonNode::swap(JsonNode &b)
swap(meta, b.meta);
swap(data, b.data);
swap(type, b.type);
swap(flags, b.flags);
}
JsonNode & JsonNode::operator =(JsonNode node)
@ -846,7 +848,7 @@ const JsonNode & JsonUtils::getSchema(std::string URI)
return getSchemaByName(filename).resolvePointer(URI.substr(posHash + 1));
}
void JsonUtils::merge(JsonNode & dest, JsonNode & source)
void JsonUtils::merge(JsonNode & dest, JsonNode & source, bool noOverride)
{
if (dest.getType() == JsonNode::JsonType::DATA_NULL)
{
@ -872,23 +874,30 @@ void JsonUtils::merge(JsonNode & dest, JsonNode & source)
}
case JsonNode::JsonType::DATA_STRUCT:
{
//recursively merge all entries from struct
for(auto & node : source.Struct())
merge(dest[node.first], node.second);
if(!noOverride && vstd::contains(source.flags, "override"))
{
std::swap(dest, source);
}
else
{
//recursively merge all entries from struct
for(auto & node : source.Struct())
merge(dest[node.first], node.second, noOverride);
}
}
}
}
void JsonUtils::mergeCopy(JsonNode & dest, JsonNode source)
void JsonUtils::mergeCopy(JsonNode & dest, JsonNode source, bool noOverride)
{
// uses copy created in stack to safely merge two nodes
merge(dest, source);
merge(dest, source, noOverride);
}
void JsonUtils::inherit(JsonNode & descendant, const JsonNode & base)
{
JsonNode inheritedNode(base);
merge(inheritedNode,descendant);
merge(inheritedNode, descendant, true);
descendant.swap(inheritedNode);
}

View File

@ -45,8 +45,10 @@ private:
JsonData data;
public:
/// free to use metadata field
/// free to use metadata fields
std::string meta;
// meta-flags like override
std::vector<std::string> flags;
//Create empty node
JsonNode(JsonType Type = JsonType::DATA_NULL);
@ -119,6 +121,10 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & meta;
if(version >= 782)
{
h & flags;
}
h & type;
switch(type)
{
@ -173,7 +179,7 @@ namespace JsonUtils
* null : if value in source is present but set to null it will delete entry in dest
* @note this function will destroy data in source
*/
DLL_LINKAGE void merge(JsonNode & dest, JsonNode & source);
DLL_LINKAGE void merge(JsonNode & dest, JsonNode & source, bool noOverride = false);
/**
* @brief recursively merges source into dest, replacing identical fields
@ -183,7 +189,7 @@ namespace JsonUtils
* null : if value in source is present but set to null it will delete entry in dest
* @note this function will preserve data stored in source by creating copy
*/
DLL_LINKAGE void mergeCopy(JsonNode & dest, JsonNode source);
DLL_LINKAGE void mergeCopy(JsonNode & dest, JsonNode source, bool noOverride = false);
/** @brief recursively merges descendant into copy of base node
* Result emulates inheritance semantic

View File

@ -12,7 +12,7 @@
#include "../ConstTransitivePtr.h"
#include "../GameConstants.h"
const ui32 SERIALIZATION_VERSION = 781;
const ui32 SERIALIZATION_VERSION = 782;
const ui32 MINIMAL_SERIALIZATION_VERSION = 753;
const std::string SAVEGAME_MAGIC = "VCMISVG";