mirror of
https://github.com/nlohmann/json.git
synced 2025-08-09 05:22:48 +03:00
♻️ allow patch and diff to be used with arbitrary string types (#4536)
This commit is contained in:
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <iterator> // forward_iterator_tag
|
#include <iterator> // forward_iterator_tag
|
||||||
#include <string> // string, to_string
|
|
||||||
#include <tuple> // tuple_size, get, tuple_element
|
#include <tuple> // tuple_size, get, tuple_element
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
@@ -20,19 +19,13 @@
|
|||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
#include <nlohmann/detail/string_utils.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename string_type>
|
|
||||||
void int_to_string( string_type& target, std::size_t value )
|
|
||||||
{
|
|
||||||
// For ADL
|
|
||||||
using std::to_string;
|
|
||||||
target = to_string(value);
|
|
||||||
}
|
|
||||||
template<typename IteratorType> class iteration_proxy_value
|
template<typename IteratorType> class iteration_proxy_value
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
37
include/nlohmann/detail/string_utils.hpp
Normal file
37
include/nlohmann/detail/string_utils.hpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.11.3
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <string> // string, to_string
|
||||||
|
|
||||||
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename StringType>
|
||||||
|
void int_to_string(StringType& target, std::size_t value)
|
||||||
|
{
|
||||||
|
// For ADL
|
||||||
|
using std::to_string;
|
||||||
|
target = to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType>
|
||||||
|
StringType to_string(std::size_t value)
|
||||||
|
{
|
||||||
|
StringType result;
|
||||||
|
int_to_string(result, value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
@@ -52,6 +52,7 @@
|
|||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/string_concat.hpp>
|
#include <nlohmann/detail/string_concat.hpp>
|
||||||
#include <nlohmann/detail/string_escape.hpp>
|
#include <nlohmann/detail/string_escape.hpp>
|
||||||
|
#include <nlohmann/detail/string_utils.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
#include <nlohmann/detail/output/binary_writer.hpp>
|
#include <nlohmann/detail/output/binary_writer.hpp>
|
||||||
@@ -4702,7 +4703,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// the valid JSON Patch operations
|
// the valid JSON Patch operations
|
||||||
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
|
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
|
||||||
|
|
||||||
const auto get_op = [](const std::string & op)
|
const auto get_op = [](const string_t& op)
|
||||||
{
|
{
|
||||||
if (op == "add")
|
if (op == "add")
|
||||||
{
|
{
|
||||||
@@ -4839,8 +4840,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
for (const auto& val : json_patch)
|
for (const auto& val : json_patch)
|
||||||
{
|
{
|
||||||
// wrapper to get a value for an operation
|
// wrapper to get a value for an operation
|
||||||
const auto get_value = [&val](const std::string & op,
|
const auto get_value = [&val](const string_t& op,
|
||||||
const std::string & member,
|
const string_t& member,
|
||||||
bool string_type) -> basic_json &
|
bool string_type) -> basic_json &
|
||||||
{
|
{
|
||||||
// find value
|
// find value
|
||||||
@@ -4874,8 +4875,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// collect mandatory members
|
// collect mandatory members
|
||||||
const auto op = get_value("op", "op", true).template get<std::string>();
|
const auto op = get_value("op", "op", true).template get<string_t>();
|
||||||
const auto path = get_value(op, "path", true).template get<std::string>();
|
const auto path = get_value(op, "path", true).template get<string_t>();
|
||||||
json_pointer ptr(path);
|
json_pointer ptr(path);
|
||||||
|
|
||||||
switch (get_op(op))
|
switch (get_op(op))
|
||||||
@@ -4901,7 +4902,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
case patch_operations::move:
|
case patch_operations::move:
|
||||||
{
|
{
|
||||||
const auto from_path = get_value("move", "from", true).template get<std::string>();
|
const auto from_path = get_value("move", "from", true).template get<string_t>();
|
||||||
json_pointer from_ptr(from_path);
|
json_pointer from_ptr(from_path);
|
||||||
|
|
||||||
// the "from" location must exist - use at()
|
// the "from" location must exist - use at()
|
||||||
@@ -4918,7 +4919,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
case patch_operations::copy:
|
case patch_operations::copy:
|
||||||
{
|
{
|
||||||
const auto from_path = get_value("copy", "from", true).template get<std::string>();
|
const auto from_path = get_value("copy", "from", true).template get<string_t>();
|
||||||
const json_pointer from_ptr(from_path);
|
const json_pointer from_ptr(from_path);
|
||||||
|
|
||||||
// the "from" location must exist - use at()
|
// the "from" location must exist - use at()
|
||||||
@@ -4978,7 +4979,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/diff/
|
/// @sa https://json.nlohmann.me/api/basic_json/diff/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||||
static basic_json diff(const basic_json& source, const basic_json& target,
|
static basic_json diff(const basic_json& source, const basic_json& target,
|
||||||
const std::string& path = "")
|
const string_t& path = "")
|
||||||
{
|
{
|
||||||
// the patch
|
// the patch
|
||||||
basic_json result(value_t::array);
|
basic_json result(value_t::array);
|
||||||
@@ -5008,7 +5009,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
while (i < source.size() && i < target.size())
|
while (i < source.size() && i < target.size())
|
||||||
{
|
{
|
||||||
// recursive call to compare array values at index i
|
// recursive call to compare array values at index i
|
||||||
auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
|
auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
|
||||||
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -5025,7 +5026,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
result.insert(result.begin() + end_index, object(
|
result.insert(result.begin() + end_index, object(
|
||||||
{
|
{
|
||||||
{"op", "remove"},
|
{"op", "remove"},
|
||||||
{"path", detail::concat(path, '/', std::to_string(i))}
|
{"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
|
||||||
}));
|
}));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -5036,7 +5037,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
result.push_back(
|
result.push_back(
|
||||||
{
|
{
|
||||||
{"op", "add"},
|
{"op", "add"},
|
||||||
{"path", detail::concat(path, "/-")},
|
{"path", detail::concat<string_t>(path, "/-")},
|
||||||
{"value", target[i]}
|
{"value", target[i]}
|
||||||
});
|
});
|
||||||
++i;
|
++i;
|
||||||
@@ -5051,7 +5052,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
for (auto it = source.cbegin(); it != source.cend(); ++it)
|
for (auto it = source.cbegin(); it != source.cend(); ++it)
|
||||||
{
|
{
|
||||||
// escape the key name to be used in a JSON patch
|
// escape the key name to be used in a JSON patch
|
||||||
const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
|
const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
|
||||||
|
|
||||||
if (target.find(it.key()) != target.end())
|
if (target.find(it.key()) != target.end())
|
||||||
{
|
{
|
||||||
@@ -5075,7 +5076,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
if (source.find(it.key()) == source.end())
|
if (source.find(it.key()) == source.end())
|
||||||
{
|
{
|
||||||
// found a key that is not in this -> add it
|
// found a key that is not in this -> add it
|
||||||
const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
|
const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
|
||||||
result.push_back(
|
result.push_back(
|
||||||
{
|
{
|
||||||
{"op", "add"}, {"path", path_key},
|
{"op", "add"}, {"path", path_key},
|
||||||
|
@@ -5275,7 +5275,6 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <iterator> // forward_iterator_tag
|
#include <iterator> // forward_iterator_tag
|
||||||
#include <string> // string, to_string
|
|
||||||
#include <tuple> // tuple_size, get, tuple_element
|
#include <tuple> // tuple_size, get, tuple_element
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
@@ -5287,6 +5286,46 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
// #include <nlohmann/detail/meta/type_traits.hpp>
|
// #include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/string_utils.hpp>
|
||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.11.3
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <string> // string, to_string
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename StringType>
|
||||||
|
void int_to_string(StringType& target, std::size_t value)
|
||||||
|
{
|
||||||
|
// For ADL
|
||||||
|
using std::to_string;
|
||||||
|
target = to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType>
|
||||||
|
StringType to_string(std::size_t value)
|
||||||
|
{
|
||||||
|
StringType result;
|
||||||
|
int_to_string(result, value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
// #include <nlohmann/detail/value_t.hpp>
|
// #include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
|
|
||||||
@@ -5294,13 +5333,6 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename string_type>
|
|
||||||
void int_to_string( string_type& target, std::size_t value )
|
|
||||||
{
|
|
||||||
// For ADL
|
|
||||||
using std::to_string;
|
|
||||||
target = to_string(value);
|
|
||||||
}
|
|
||||||
template<typename IteratorType> class iteration_proxy_value
|
template<typename IteratorType> class iteration_proxy_value
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -15125,6 +15157,8 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
// #include <nlohmann/detail/string_escape.hpp>
|
// #include <nlohmann/detail/string_escape.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/string_utils.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/meta/cpp_future.hpp>
|
// #include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/meta/type_traits.hpp>
|
// #include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
@@ -24249,7 +24283,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// the valid JSON Patch operations
|
// the valid JSON Patch operations
|
||||||
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
|
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
|
||||||
|
|
||||||
const auto get_op = [](const std::string & op)
|
const auto get_op = [](const string_t& op)
|
||||||
{
|
{
|
||||||
if (op == "add")
|
if (op == "add")
|
||||||
{
|
{
|
||||||
@@ -24386,8 +24420,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
for (const auto& val : json_patch)
|
for (const auto& val : json_patch)
|
||||||
{
|
{
|
||||||
// wrapper to get a value for an operation
|
// wrapper to get a value for an operation
|
||||||
const auto get_value = [&val](const std::string & op,
|
const auto get_value = [&val](const string_t& op,
|
||||||
const std::string & member,
|
const string_t& member,
|
||||||
bool string_type) -> basic_json &
|
bool string_type) -> basic_json &
|
||||||
{
|
{
|
||||||
// find value
|
// find value
|
||||||
@@ -24421,8 +24455,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// collect mandatory members
|
// collect mandatory members
|
||||||
const auto op = get_value("op", "op", true).template get<std::string>();
|
const auto op = get_value("op", "op", true).template get<string_t>();
|
||||||
const auto path = get_value(op, "path", true).template get<std::string>();
|
const auto path = get_value(op, "path", true).template get<string_t>();
|
||||||
json_pointer ptr(path);
|
json_pointer ptr(path);
|
||||||
|
|
||||||
switch (get_op(op))
|
switch (get_op(op))
|
||||||
@@ -24448,7 +24482,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
case patch_operations::move:
|
case patch_operations::move:
|
||||||
{
|
{
|
||||||
const auto from_path = get_value("move", "from", true).template get<std::string>();
|
const auto from_path = get_value("move", "from", true).template get<string_t>();
|
||||||
json_pointer from_ptr(from_path);
|
json_pointer from_ptr(from_path);
|
||||||
|
|
||||||
// the "from" location must exist - use at()
|
// the "from" location must exist - use at()
|
||||||
@@ -24465,7 +24499,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
case patch_operations::copy:
|
case patch_operations::copy:
|
||||||
{
|
{
|
||||||
const auto from_path = get_value("copy", "from", true).template get<std::string>();
|
const auto from_path = get_value("copy", "from", true).template get<string_t>();
|
||||||
const json_pointer from_ptr(from_path);
|
const json_pointer from_ptr(from_path);
|
||||||
|
|
||||||
// the "from" location must exist - use at()
|
// the "from" location must exist - use at()
|
||||||
@@ -24525,7 +24559,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/diff/
|
/// @sa https://json.nlohmann.me/api/basic_json/diff/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||||
static basic_json diff(const basic_json& source, const basic_json& target,
|
static basic_json diff(const basic_json& source, const basic_json& target,
|
||||||
const std::string& path = "")
|
const string_t& path = "")
|
||||||
{
|
{
|
||||||
// the patch
|
// the patch
|
||||||
basic_json result(value_t::array);
|
basic_json result(value_t::array);
|
||||||
@@ -24555,7 +24589,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
while (i < source.size() && i < target.size())
|
while (i < source.size() && i < target.size())
|
||||||
{
|
{
|
||||||
// recursive call to compare array values at index i
|
// recursive call to compare array values at index i
|
||||||
auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
|
auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
|
||||||
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -24572,7 +24606,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
result.insert(result.begin() + end_index, object(
|
result.insert(result.begin() + end_index, object(
|
||||||
{
|
{
|
||||||
{"op", "remove"},
|
{"op", "remove"},
|
||||||
{"path", detail::concat(path, '/', std::to_string(i))}
|
{"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
|
||||||
}));
|
}));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -24583,7 +24617,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
result.push_back(
|
result.push_back(
|
||||||
{
|
{
|
||||||
{"op", "add"},
|
{"op", "add"},
|
||||||
{"path", detail::concat(path, "/-")},
|
{"path", detail::concat<string_t>(path, "/-")},
|
||||||
{"value", target[i]}
|
{"value", target[i]}
|
||||||
});
|
});
|
||||||
++i;
|
++i;
|
||||||
@@ -24598,7 +24632,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
for (auto it = source.cbegin(); it != source.cend(); ++it)
|
for (auto it = source.cbegin(); it != source.cend(); ++it)
|
||||||
{
|
{
|
||||||
// escape the key name to be used in a JSON patch
|
// escape the key name to be used in a JSON patch
|
||||||
const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
|
const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
|
||||||
|
|
||||||
if (target.find(it.key()) != target.end())
|
if (target.find(it.key()) != target.end())
|
||||||
{
|
{
|
||||||
@@ -24622,7 +24656,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
if (source.find(it.key()) == source.end())
|
if (source.find(it.key()) == source.end())
|
||||||
{
|
{
|
||||||
// found a key that is not in this -> add it
|
// found a key that is not in this -> add it
|
||||||
const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
|
const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
|
||||||
result.push_back(
|
result.push_back(
|
||||||
{
|
{
|
||||||
{"op", "add"}, {"path", path_key},
|
{"op", "add"}, {"path", path_key},
|
||||||
|
@@ -35,10 +35,21 @@ class alt_string
|
|||||||
alt_string(size_t count, char chr): str_impl(count, chr) {}
|
alt_string(size_t count, char chr): str_impl(count, chr) {}
|
||||||
alt_string() = default;
|
alt_string() = default;
|
||||||
|
|
||||||
template <typename...TParams>
|
alt_string& append(char ch)
|
||||||
alt_string& append(TParams&& ...params)
|
|
||||||
{
|
{
|
||||||
str_impl.append(std::forward<TParams>(params)...);
|
str_impl.push_back(ch);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
alt_string& append(const alt_string& str)
|
||||||
|
{
|
||||||
|
str_impl.append(str.str_impl);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
alt_string& append(const char* s, std::size_t length)
|
||||||
|
{
|
||||||
|
str_impl.append(s, length);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +168,11 @@ class alt_string
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reserve( std::size_t new_cap = 0 )
|
||||||
|
{
|
||||||
|
str_impl.reserve(new_cap);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string str_impl {}; // NOLINT(readability-redundant-member-init)
|
std::string str_impl {}; // NOLINT(readability-redundant-member-init)
|
||||||
|
|
||||||
@@ -319,4 +335,28 @@ TEST_CASE("alternative string type")
|
|||||||
CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);
|
CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);
|
||||||
CHECK(j.at(alt_json::json_pointer("/foo/1")) == j["foo"][1]);
|
CHECK(j.at(alt_json::json_pointer("/foo/1")) == j["foo"][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("patch")
|
||||||
|
{
|
||||||
|
alt_json const patch1 = alt_json::parse(R"([{ "op": "add", "path": "/a/b", "value": [ "foo", "bar" ] }])");
|
||||||
|
alt_json const doc1 = alt_json::parse(R"({ "a": { "foo": 1 } })");
|
||||||
|
|
||||||
|
CHECK_NOTHROW(doc1.patch(patch1));
|
||||||
|
alt_json doc1_ans = alt_json::parse(R"(
|
||||||
|
{
|
||||||
|
"a": {
|
||||||
|
"foo": 1,
|
||||||
|
"b": [ "foo", "bar" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
CHECK(doc1.patch(patch1) == doc1_ans);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("diff")
|
||||||
|
{
|
||||||
|
alt_json const j1 = {"foo", "bar", "baz"};
|
||||||
|
alt_json const j2 = {"foo", "bam"};
|
||||||
|
CHECK(alt_json::diff(j1, j2).dump() == "[{\"op\":\"replace\",\"path\":\"/1\",\"value\":\"bam\"},{\"op\":\"remove\",\"path\":\"/2\"}]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user