MCPcopy Create free account
hub / github.com/chigraph/chigraph / diff

Function diff

libchigraph/include/chi/json.hpp:10914–11000  ·  view source on GitHub ↗

! @brief creates a diff as a JSON patch Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can be changed into the value @a target by calling @ref patch function. @invariant For two JSON values @a source and @a target, the following code yields always `true`: @code {.cpp} source.patch(diff(source, target)) == target; @endcode @note Currently, only `remove`, `add`, and

Source from the content-addressed store, hash-verified

10912 @since version 2.0.0
10913 */
10914 static basic_json diff(const basic_json& source, const basic_json& target,
10915 const std::string& path = "") {
10916 // the patch
10917 basic_json result(value_t::array);
10918
10919 // if the values are the same, return empty patch
10920 if (source == target) { return result; }
10921
10922 if (source.type() != target.type()) {
10923 // different types: replace value
10924 result.push_back({{"op", "replace"}, {"path", path}, {"value", target}});
10925 } else {
10926 switch (source.type()) {
10927 case value_t::array: {
10928 // first pass: traverse common elements
10929 size_t i = 0;
10930 while (i < source.size() and i < target.size()) {
10931 // recursive call to compare array values at index i
10932 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
10933 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10934 ++i;
10935 }
10936
10937 // i now reached the end of at least one array
10938 // in a second pass, traverse the remaining elements
10939
10940 // remove my remaining elements
10941 const auto end_index = static_cast<difference_type>(result.size());
10942 while (i < source.size()) {
10943 // add operations in reverse order to avoid invalid
10944 // indices
10945 result.insert(
10946 result.begin() + end_index,
10947 object({{"op", "remove"}, {"path", path + "/" + std::to_string(i)}}));
10948 ++i;
10949 }
10950
10951 // add other remaining elements
10952 while (i < target.size()) {
10953 result.push_back({{"op", "add"},
10954 {"path", path + "/" + std::to_string(i)},
10955 {"value", target[i]}});
10956 ++i;
10957 }
10958
10959 break;
10960 }
10961
10962 case value_t::object: {
10963 // first pass: traverse this object's elements
10964 for (auto it = source.begin(); it != source.end(); ++it) {
10965 // escape the key name to be used in a JSON patch
10966 const auto key = json_pointer::escape(it.key());
10967
10968 if (target.find(it.key()) != target.end()) {
10969 // recursive call to compare object values at key it
10970 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10971 result.insert(result.end(), temp_diff.begin(), temp_diff.end());

Callers

nothing calls this directly

Calls 5

typeMethod · 0.80
endMethod · 0.80
beginMethod · 0.80
keyMethod · 0.45
valueMethod · 0.45

Tested by

no test coverage detected