616caea27a
* Make exception context optional Change exception context parameter to pointer and replace context with nullptr where appropriate. * Support escaping other string types * Add string concatenation function Add variadic concat() function for concatenating char *, char, and string types. * Replace string concatenations using + with concat() * Template json_pointer on string type Change json_pointer from being templated on basic_json to being templated on string type. * Add unit test for #3388 Closes #3388. * Fix regression test for #2958 * Add backwards compatibility with json_pointer<basic_json> * Update json_pointer docs * Allow comparing different json_pointers * Update version numbers
140 lines
5.6 KiB
C++
140 lines
5.6 KiB
C++
#pragma once
|
|
|
|
#include <cstring> // strlen
|
|
#include <string> // string
|
|
#include <utility> // forward
|
|
|
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
|
#include <nlohmann/detail/meta/detected.hpp>
|
|
|
|
namespace nlohmann
|
|
{
|
|
namespace detail
|
|
{
|
|
|
|
inline std::size_t concat_length()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
template<typename... Args>
|
|
inline std::size_t concat_length(const char* cstr, Args&& ... rest);
|
|
|
|
template<typename StringType, typename... Args>
|
|
inline std::size_t concat_length(const StringType& str, Args&& ... rest);
|
|
|
|
template<typename... Args>
|
|
inline std::size_t concat_length(const char /*c*/, Args&& ... rest)
|
|
{
|
|
return 1 + concat_length(std::forward<Args>(rest)...);
|
|
}
|
|
|
|
template<typename... Args>
|
|
inline std::size_t concat_length(const char* cstr, Args&& ... rest)
|
|
{
|
|
// cppcheck-suppress ignoredReturnValue
|
|
return ::strlen(cstr) + concat_length(std::forward<Args>(rest)...);
|
|
}
|
|
|
|
template<typename StringType, typename... Args>
|
|
inline std::size_t concat_length(const StringType& str, Args&& ... rest)
|
|
{
|
|
return str.size() + concat_length(std::forward<Args>(rest)...);
|
|
}
|
|
|
|
template<typename OutStringType>
|
|
inline void concat_into(OutStringType& /*out*/)
|
|
{}
|
|
|
|
template<typename StringType, typename Arg>
|
|
using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
|
|
|
|
template<typename StringType, typename Arg>
|
|
using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
|
|
|
|
template<typename StringType, typename Arg>
|
|
using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
|
|
|
|
template<typename StringType, typename Arg>
|
|
using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
|
|
|
|
template<typename StringType, typename Arg>
|
|
using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
|
|
|
|
template<typename StringType, typename Arg>
|
|
using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
|
|
|
|
template<typename StringType, typename Arg>
|
|
using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
|
|
|
|
template<typename StringType, typename Arg>
|
|
using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
|
|
|
|
template < typename OutStringType, typename Arg, typename... Args,
|
|
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
|
&& detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
|
|
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
|
|
|
|
template < typename OutStringType, typename Arg, typename... Args,
|
|
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
|
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
|
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
|
|
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
|
|
|
|
template < typename OutStringType, typename Arg, typename... Args,
|
|
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
|
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
|
&& !detect_string_can_append_iter<OutStringType, Arg>::value
|
|
&& detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
|
|
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
|
|
|
|
template<typename OutStringType, typename Arg, typename... Args,
|
|
enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
|
|
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
|
|
{
|
|
out.append(std::forward<Arg>(arg));
|
|
concat_into(out, std::forward<Args>(rest)...);
|
|
}
|
|
|
|
template < typename OutStringType, typename Arg, typename... Args,
|
|
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
|
&& detect_string_can_append_op<OutStringType, Arg>::value, int > >
|
|
inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
|
|
{
|
|
out += std::forward<Arg>(arg);
|
|
concat_into(out, std::forward<Args>(rest)...);
|
|
}
|
|
|
|
template < typename OutStringType, typename Arg, typename... Args,
|
|
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
|
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
|
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > >
|
|
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
|
|
{
|
|
out.append(arg.begin(), arg.end());
|
|
concat_into(out, std::forward<Args>(rest)...);
|
|
}
|
|
|
|
template < typename OutStringType, typename Arg, typename... Args,
|
|
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
|
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
|
&& !detect_string_can_append_iter<OutStringType, Arg>::value
|
|
&& detect_string_can_append_data<OutStringType, Arg>::value, int > >
|
|
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
|
|
{
|
|
out.append(arg.data(), arg.size());
|
|
concat_into(out, std::forward<Args>(rest)...);
|
|
}
|
|
|
|
template<typename OutStringType = std::string, typename... Args>
|
|
inline OutStringType concat(Args && ... args)
|
|
{
|
|
OutStringType str;
|
|
str.reserve(concat_length(std::forward<Args>(args)...));
|
|
concat_into(str, std::forward<Args>(args)...);
|
|
return str;
|
|
}
|
|
|
|
} // namespace detail
|
|
} // namespace nlohmann
|