diff --git a/CMakeLists.txt b/CMakeLists.txt index 53406e5a..c9c68e93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ endif() project(PIP) set(PIP_MAJOR 5) set(PIP_MINOR 5) -set(PIP_REVISION 3) +set(PIP_REVISION 4) set(PIP_SUFFIX ) set(PIP_COMPANY SHS) set(PIP_DOMAIN org.SHS) diff --git a/libs/main/serialization/pijson.cpp b/libs/main/serialization/pijson.cpp index a917f97c..8ef17798 100644 --- a/libs/main/serialization/pijson.cpp +++ b/libs/main/serialization/pijson.cpp @@ -400,9 +400,9 @@ PIJSON PIJSON::parseValue(PIString & s) { s.trim(); if (s.isEmpty()) return ret; if (s[0] == '{') { - ret = parseObject(s.takeRange('{', '}')); + ret = parseObject(s.takeRange('{', '}').trim()); } else if (s[0] == '[') { - ret = parseArray(s.takeRange('[', ']')); + ret = parseArray(s.takeRange('[', ']').trim()); } else { s.trim(); if (s.startsWith('"')) { diff --git a/libs/main/serialization/pivaluetree_conversions.cpp b/libs/main/serialization/pivaluetree_conversions.cpp index f3419650..1a84d15c 100644 --- a/libs/main/serialization/pivaluetree_conversions.cpp +++ b/libs/main/serialization/pivaluetree_conversions.cpp @@ -42,6 +42,14 @@ PIString mask(const PIString & str) { return ret; } +PIString overrideFile(PIString path) { + if (path.isEmpty()) return {}; + PIFile::FileInfo fi(path); + auto ext = fi.extension(); + path.insert(path.size_s() - ext.size_s() - (ext.isEmpty() ? 0 : 1), ".override"); + return path; +} + PIValueTree PIValueTreeConversions::fromPropertyStorage(const PIPropertyStorage & ps) { PIValueTree ret; @@ -292,7 +300,11 @@ PIString toTextTree(const PIValueTree & root, PIString prefix, PIValueTreeConver ret += "\n[" + prefix + "]\n"; if (root.isArray() && options[PIValueTreeConversions::WithAttributes]) ret += toTextTreeAttributes(root, "", options); for (const auto & c: root.children()) { - PIString cp = prefix; + if (c.hasChildren()) continue; + ret += toTextTree(c, prefix, options); + } + for (const auto & c: root.children()) { + if (!c.hasChildren()) continue; ret += toTextTree(c, prefix, options); } } else { @@ -315,9 +327,13 @@ PIString toTextTree(const PIValueTree & root, PIString prefix, PIValueTreeConver PIString PIValueTreeConversions::toText(const PIValueTree & root, Options options) { PIString ret; for (const auto & c: root.children()) { - ret += toTextTree(c, PIString(), options); + if (c.hasChildren()) continue; + ret += toTextTree(c, {}, options); + } + for (const auto & c: root.children()) { + if (!c.hasChildren()) continue; + ret += toTextTree(c, {}, options); } - return ret; } @@ -329,13 +345,26 @@ PIValueTree PIValueTreeConversions::fromText(const PIString & str) { PIValueTree PIValueTreeConversions::fromJSONFile(const PIString & path) { - return PIValueTreeConversions::fromJSON(PIJSON::fromJSON(PIString::fromUTF8(PIFile::readAll(path)))); + auto ret = PIValueTreeConversions::fromJSON(PIJSON::fromJSON(PIString::fromUTF8(PIFile::readAll(path)))); + auto ofp = overrideFile(path); + if (PIFile::isExists(ofp)) { + auto override = PIValueTreeConversions::fromJSON(PIJSON::fromJSON(PIString::fromUTF8(PIFile::readAll(ofp)))); + ret.merge(override); + } + return ret; } PIValueTree PIValueTreeConversions::fromTextFile(const PIString & path) { PIFile f(path, PIIODevice::ReadOnly); - return PIValueTreeConversions::fromText(&f); + auto ret = PIValueTreeConversions::fromText(&f); + auto ofp = overrideFile(path); + if (PIFile::isExists(ofp)) { + PIFile of(ofp, PIIODevice::ReadOnly); + auto override = PIValueTreeConversions::fromText(&of); + ret.merge(override); + } + return ret; } diff --git a/libs/main/types/pivaluetree.cpp b/libs/main/types/pivaluetree.cpp index 2d292039..b21f6279 100644 --- a/libs/main/types/pivaluetree.cpp +++ b/libs/main/types/pivaluetree.cpp @@ -124,6 +124,23 @@ void PIValueTree::applyValues(const PIValueTree & root, bool recursive) { } +void PIValueTree::merge(const PIValueTree & root) { + if (_is_null) return; + for (const auto & c: root._children) { + bool found = false; + for (auto & i: _children) { + if (c.name() == i.name()) { + if (c.isValid()) i._value = c._value; + i.merge(c); + found = true; + break; + } + } + if (!found) _children << c; + } +} + + PIVariant PIValueTree::childValue(const PIString & child_name, const PIVariant & default_value, bool * exists) const { const PIValueTree & node = child(child_name); if (node.isNull()) { diff --git a/libs/main/types/pivaluetree.h b/libs/main/types/pivaluetree.h index 323a6a9e..d9ee4865 100644 --- a/libs/main/types/pivaluetree.h +++ b/libs/main/types/pivaluetree.h @@ -170,6 +170,13 @@ public: //! \param recursive Если установлено в true, то значения будут применяться рекурсивно к дочерним узлам. void applyValues(const PIValueTree & root, bool recursive = true); + //! \~\brief + //! \~english Set or add the values of a given %PIValueTree object to the current %PIValueTree object. + //! \param root The %PIValueTree object whose values are to be merged. + //! \~russian Устанавливает или добавляет значения данного объекта %PIValueTree к текущему объекту %PIValueTree. + //! \param root Объект %PIValueTree, значения которого должны быть добавлены. + void merge(const PIValueTree & root); + //! \~\brief //! \~english Returns the children of the current %PIValueTree object. //! \~russian Возвращает дочерние элементы текущего объекта %PIValueTree.