diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-04-20 13:49:33 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-04-20 13:49:33 +0300 |
commit | d85809f7b86d53a83de4744b395e61df085e727f (patch) | |
tree | 32093c9bdbaa6c4ab42f34f38cfb6f401ec46d4d /library/cpp | |
parent | f8b13db877cf0234f2bdf7092164f57eebc52aa1 (diff) | |
download | ydb-d85809f7b86d53a83de4744b395e61df085e727f.tar.gz |
intermediate changes
ref:95923961b070d9d9b37fcb1d21bffeae90f3d022
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/scheme/scheme.cpp | 57 | ||||
-rw-r--r-- | library/cpp/scheme/scheme.h | 26 | ||||
-rw-r--r-- | library/cpp/scheme/tests/ut/scheme_merge_ut.cpp | 63 |
3 files changed, 122 insertions, 24 deletions
diff --git a/library/cpp/scheme/scheme.cpp b/library/cpp/scheme/scheme.cpp index 3efd116d4f1..e6b59e8346f 100644 --- a/library/cpp/scheme/scheme.cpp +++ b/library/cpp/scheme/scheme.cpp @@ -28,39 +28,39 @@ namespace NSc { return bufs; } - TValue& TValue::MergeUpdate(const TValue& delta) { - return DoMerge(delta, false); + TValue& TValue::MergeUpdate(const TValue& delta, TMaybe<TMergeOptions> mergeOptions) { + return DoMerge(delta, false, mergeOptions); } - TValue& TValue::ReverseMerge(const TValue& delta) { - return DoMerge(delta, true); + TValue& TValue::ReverseMerge(const TValue& delta, TMaybe<TMergeOptions> mergeOptions) { + return DoMerge(delta, true, mergeOptions); } - TValue& TValue::MergeUpdateJson(TStringBuf data) { - return MergeUpdate(FromJson(data)); + TValue& TValue::MergeUpdateJson(TStringBuf data, TMaybe<TMergeOptions> mergeOptions) { + return MergeUpdate(FromJson(data), mergeOptions); } - TValue& TValue::ReverseMergeJson(TStringBuf data) { - return ReverseMerge(FromJson(data)); + TValue& TValue::ReverseMergeJson(TStringBuf data, TMaybe<TMergeOptions> mergeOptions) { + return ReverseMerge(FromJson(data), mergeOptions); } - bool TValue::MergeUpdateJson(TValue& v, TStringBuf data) { + bool TValue::MergeUpdateJson(TValue& v, TStringBuf data, TMaybe<TMergeOptions> mergeOptions) { NSc::TValue m; if (!FromJson(m, data)) { return false; } - v.MergeUpdate(m); + v.MergeUpdate(m, mergeOptions); return true; } - bool TValue::ReverseMergeJson(TValue& v, TStringBuf data) { + bool TValue::ReverseMergeJson(TValue& v, TStringBuf data, TMaybe<TMergeOptions> mergeOptions) { NSc::TValue m; if (!FromJson(m, data)) { return false; } - v.ReverseMerge(m); + v.ReverseMerge(m, mergeOptions); return true; } @@ -290,22 +290,24 @@ namespace NSc { return true; } - TValue& TValue::DoMerge(const TValue& delta, bool lowPriorityDelta) { + TValue& TValue::DoMerge(const TValue& delta, bool lowPriorityDelta, TMaybe<TMergeOptions> mergeOptions) { if (Same(*this, delta)) { return *this; } using namespace NImpl; - return DoMergeImpl(delta, lowPriorityDelta, GetTlsInstance<TSelfLoopContext>(), GetTlsInstance<TSelfOverrideContext>()); + return DoMergeImpl(delta, lowPriorityDelta, mergeOptions, GetTlsInstance<TSelfLoopContext>(), GetTlsInstance<TSelfOverrideContext>()); } - TValue& TValue::DoMergeImpl(const TValue& delta, bool lowPriorityDelta, + TValue& TValue::DoMergeImpl(const TValue& delta, bool lowPriorityDelta, TMaybe<TMergeOptions> mergeOptions, NImpl::TSelfLoopContext& otherLoopCtx, NImpl::TSelfOverrideContext& selfOverrideGuard) { if (Same(*this, delta)) { return *this; } + bool allowMergeArray = mergeOptions.Defined() && mergeOptions->ArrayMergeMode == TMergeOptions::EArrayMergeMode::Merge; + if (delta.IsDict() && (!lowPriorityDelta || IsDict() || IsNull())) { TScCore& core = CoreMutable(); const TScCore& deltaCore = delta.Core(); @@ -323,7 +325,30 @@ namespace NSc { const TDict& ddelta = deltaCore.Dict; for (const auto& dit : ddelta) { - core.GetOrAdd(dit.first).DoMergeImpl(dit.second, lowPriorityDelta, otherLoopCtx, selfOverrideGuard); + core.GetOrAdd(dit.first).DoMergeImpl(dit.second, lowPriorityDelta, mergeOptions, otherLoopCtx, selfOverrideGuard); + } + } else if (delta.IsArray() && allowMergeArray && (!lowPriorityDelta || IsArray() || IsNull())) { + TScCore& core = CoreMutable(); + const TScCore& deltaCore = delta.Core(); + + NImpl::TSelfLoopContext::TGuard loopCheck(otherLoopCtx, deltaCore); + + if (!loopCheck.Ok) { + return *this; // a loop encountered (and asserted), skip the back reference + } + + if (!lowPriorityDelta || IsNull()) { + SetArray(); + } + + Y_ASSERT(IsArray()); + + const TArray& adelta = deltaCore.Array; + if (adelta.size() > core.Array.size()) { + core.Array.resize(adelta.size()); + } + for (size_t i = 0; i < adelta.size(); ++i) { + core.Array[i].DoMergeImpl(adelta[i], lowPriorityDelta, mergeOptions, otherLoopCtx, selfOverrideGuard); } } else if (!delta.IsNull() && (!lowPriorityDelta || IsNull())) { DoCopyFromImpl(delta, otherLoopCtx, selfOverrideGuard); diff --git a/library/cpp/scheme/scheme.h b/library/cpp/scheme/scheme.h index cc0699c67ac..b4cb98c9677 100644 --- a/library/cpp/scheme/scheme.h +++ b/library/cpp/scheme/scheme.h @@ -4,6 +4,8 @@ #include "fwd.h" +#include <util/generic/maybe.h> + #include <iterator> #include <utility> @@ -12,6 +14,14 @@ namespace NSc { #pragma warning(disable : 4521 4522) #endif + struct TMergeOptions { + enum class EArrayMergeMode { + Replace, + Merge + }; + EArrayMergeMode ArrayMergeMode = EArrayMergeMode::Replace; + }; + // todo: try to remove some rarely used methods class TValue { public: @@ -341,14 +351,14 @@ namespace NSc { * - Do nothing. */ - TValue& MergeUpdateJson(TStringBuf json); // returns self - TValue& ReverseMergeJson(TStringBuf json); // returns self + TValue& MergeUpdateJson(TStringBuf json, TMaybe<TMergeOptions> mergeOptions = {}); // returns self + TValue& ReverseMergeJson(TStringBuf json, TMaybe<TMergeOptions> mergeOptions = {}); // returns self - static bool MergeUpdateJson(TValue&, TStringBuf json); // returns true unless failed to parse the json - static bool ReverseMergeJson(TValue&, TStringBuf json); // returns true unless failed to parse the json + static bool MergeUpdateJson(TValue&, TStringBuf json, TMaybe<TMergeOptions> mergeOptions = {}); // returns true unless failed to parse the json + static bool ReverseMergeJson(TValue&, TStringBuf json, TMaybe<TMergeOptions> mergeOptions = {}); // returns true unless failed to parse the json - TValue& MergeUpdate(const TValue& delta); // return self - TValue& ReverseMerge(const TValue& delta); // return self + TValue& MergeUpdate(const TValue& delta, TMaybe<TMergeOptions> mergeOptions = {}); // return self + TValue& ReverseMerge(const TValue& delta, TMaybe<TMergeOptions> mergeOptions = {}); // return self public: // Path methods ///////////////////////////////////////////////////////// // TODO: add throwing variants @@ -405,8 +415,8 @@ namespace NSc { bool IsSameOrAncestorOf(const TValue& other) const; private: - TValue& DoMerge(const TValue& delta, bool olddelta); - TValue& DoMergeImpl(const TValue& delta, bool olddelta, NImpl::TSelfLoopContext&, NImpl::TSelfOverrideContext&); + TValue& DoMerge(const TValue& delta, bool olddelta, TMaybe<TMergeOptions> mergeOptions); + TValue& DoMergeImpl(const TValue& delta, bool olddelta, TMaybe<TMergeOptions> mergeOptions, NImpl::TSelfLoopContext&, NImpl::TSelfOverrideContext&); TValue& DoCopyFromImpl(const TValue& other, NImpl::TSelfLoopContext&, NImpl::TSelfOverrideContext&); NJson::TJsonValue ToJsonValueImpl(NImpl::TSelfLoopContext&) const; diff --git a/library/cpp/scheme/tests/ut/scheme_merge_ut.cpp b/library/cpp/scheme/tests/ut/scheme_merge_ut.cpp index 2a06cf110da..38c52833834 100644 --- a/library/cpp/scheme/tests/ut/scheme_merge_ut.cpp +++ b/library/cpp/scheme/tests/ut/scheme_merge_ut.cpp @@ -169,4 +169,67 @@ Y_UNIT_TEST_SUITE(TSchemeMergeTest) { UNIT_ASSERT_JSON_EQ_JSON(a, "[1,2,3]"); UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[1,2,3]}"); } + + Y_UNIT_TEST(TestMerge8) { + NSc::TValue v; + v["a"] = NSc::TValue::FromJson("[0.125,0.12,0.1,0.08,0.06]"); + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[0.125,0.12,0.1,0.08,0.06]}"); + + NSc::TMergeOptions options = {.ArrayMergeMode = NSc::TMergeOptions::EArrayMergeMode::Merge}; + NSc::TValue a = v.TrySelectOrAdd("a")->MergeUpdateJson("[1,2,3]", options); + + UNIT_ASSERT_JSON_EQ_JSON(a, "[1,2,3,0.08,0.06]"); + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[1,2,3,0.08,0.06]}"); + } + + Y_UNIT_TEST(TestMerge9) { + NSc::TValue v; + v["a"] = NSc::TValue::FromJson("[{a:1},{b:2,d:2}]"); + + NSc::TValue update; + update["a"] = NSc::TValue::FromJson("[{},{a:1,d:1},{b:2}]"); + + NSc::TMergeOptions options = {.ArrayMergeMode = NSc::TMergeOptions::EArrayMergeMode::Merge}; + v.MergeUpdate(update, options); + + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[{a:1},{a:1,b:2,d:1},{b:2}]}"); + + //no uncontrolled grow + v.MergeUpdate(update, options); + v.MergeUpdate(update, options); + + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[{a:1},{a:1,b:2,d:1},{b:2}]}"); + } + + Y_UNIT_TEST(TestMerge10) { + NSc::TValue v; + v["a"] = NSc::TValue::FromJson("[0.125,0.12,0.1,0.08,0.06]"); + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[0.125,0.12,0.1,0.08,0.06]}"); + + NSc::TMergeOptions options = {.ArrayMergeMode = NSc::TMergeOptions::EArrayMergeMode::Merge}; + NSc::TValue delta = NSc::TValue::FromJson("{a:[1,2,3,4,5,6]}"); + v.ReverseMerge(delta, options); + + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[0.125,0.12,0.1,0.08,0.06,6]}"); + } + + Y_UNIT_TEST(TestMerge11) { + NSc::TValue v; + v["a"] = NSc::TValue::FromJson("[{a:1},{b:2,d:2}]"); + + NSc::TValue update; + update["a"] = NSc::TValue::FromJson("[{},{a:1,d:1},{b:2}]"); + + NSc::TMergeOptions options = {.ArrayMergeMode = NSc::TMergeOptions::EArrayMergeMode::Merge}; + v.ReverseMerge(update, options); + + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[{a:1},{a:1,b:2,d:2},{b:2}]}"); + + //no uncontrolled grow + v.ReverseMerge(update, options); + v.ReverseMerge(update, options); + + UNIT_ASSERT_JSON_EQ_JSON(v, "{a:[{a:1},{a:1,b:2,d:2},{b:2}]}"); + } + }; |