aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/nlohmann_json/include/nlohmann/detail/string_concat.hpp
blob: f49e8d215ee250b9b6d68de0a91b93222d1fa845 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//     __ _____ _____ _____
//  __|  |   __|     |   | |  JSON for Modern C++
// |  |  |__   |  |  | | | |  version 3.11.3
// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT

#pragma once

#include <cstring> // strlen
#include <string> // string
#include <utility> // forward

#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/detected.hpp>

NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{

inline std::size_t concat_length()
{
    return 0;
}

template<typename... Args>
inline std::size_t concat_length(const char* cstr, const Args& ... rest);

template<typename StringType, typename... Args>
inline std::size_t concat_length(const StringType& str, const Args& ... rest);

template<typename... Args>
inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
{
    return 1 + concat_length(rest...);
}

template<typename... Args>
inline std::size_t concat_length(const char* cstr, const Args& ... rest)
{
    // cppcheck-suppress ignoredReturnValue
    return ::strlen(cstr) + concat_length(rest...);
}

template<typename StringType, typename... Args>
inline std::size_t concat_length(const StringType& str, const Args& ... rest)
{
    return str.size() + concat_length(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(args...));
    concat_into(str, std::forward<Args>(args)...);
    return str;
}

}  // namespace detail
NLOHMANN_JSON_NAMESPACE_END