diff options
| author | Richard <q@1bpm.net> | 2022-09-04 00:32:56 +0100 | 
|---|---|---|
| committer | Richard <q@1bpm.net> | 2022-09-04 00:32:56 +0100 | 
| commit | 1d055261b4144dbf86b2658437015b15d4dd9bff (patch) | |
| tree | 6049b19d1bf953a650383de1a5e438b8b82679f6 /include/jsoncons_ext/mergepatch | |
| download | csound-json-1d055261b4144dbf86b2658437015b15d4dd9bff.tar.gz csound-json-1d055261b4144dbf86b2658437015b15d4dd9bff.tar.bz2 csound-json-1d055261b4144dbf86b2658437015b15d4dd9bff.zip | |
initial
Diffstat (limited to 'include/jsoncons_ext/mergepatch')
| -rw-r--r-- | include/jsoncons_ext/mergepatch/mergepatch.hpp | 103 | 
1 files changed, 103 insertions, 0 deletions
| diff --git a/include/jsoncons_ext/mergepatch/mergepatch.hpp b/include/jsoncons_ext/mergepatch/mergepatch.hpp new file mode 100644 index 0000000..c5fdefe --- /dev/null +++ b/include/jsoncons_ext/mergepatch/mergepatch.hpp @@ -0,0 +1,103 @@ +// Copyright 2017 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_JSONMERGEPATCH_JSONMERGEPATCH_HPP +#define JSONCONS_JSONMERGEPATCH_JSONMERGEPATCH_HPP + +#include <string> +#include <vector>  +#include <memory> +#include <algorithm> // std::min +#include <utility> // std::move +#include <jsoncons/json.hpp> + +namespace jsoncons {  +namespace mergepatch { + +    template <class Json> +    Json from_diff(const Json& source, const Json& target) +    { +        if (!source.is_object() || !target.is_object()) +        { +            return target; +        } +        Json result(json_object_arg); + +        for (const auto& member : source.object_range()) +        { +            auto it = target.find(member.key()); +            if (it != target.object_range().end()) +            { +                if (member.value() != it->value()) +                { +                    result.try_emplace(member.key(), from_diff(member.value(), it->value())); +                } +            } +            else +            { +                result.try_emplace(member.key(), Json::null()); +            } +        } + +        for (const auto& member : target.object_range()) +        { +            auto it = source.find(member.key()); +            if (it == source.object_range().end()) +            { +                result.try_emplace(member.key(), member.value()); +            } +        } + +        return result; +    } + +    namespace detail { +        template <class Json> +        Json apply_merge_patch_(Json& target, const Json& patch) +        { +            if (patch.is_object()) +            { +                if (!target.is_object()) +                { +                    target = Json(json_object_arg); +                } +                for (auto& member : patch.object_range()) +                { +                    auto it = target.find(member.key()); +                    if (it != target.object_range().end()) +                    { +                        Json item = it->value(); +                        target.erase(it); +                        if (!member.value().is_null()) +                        { +                            target.try_emplace(member.key(), apply_merge_patch_(item, member.value())); +                        } +                    } +                    else if (!member.value().is_null()) +                    { +                        Json item(json_object_arg); +                        target.try_emplace(member.key(), apply_merge_patch_(item, member.value())); +                    } +                } +                return target; +            } +            else +            { +                return patch; +            } +        } +    } // namespace detail + +    template <class Json> +    void apply_merge_patch(Json& target, const Json& patch) +    { +        target = detail::apply_merge_patch_(target, patch); +    } + +} // namespace mergepatch +} // namespace jsoncons + +#endif |