1 #ifndef CONVERSION_UTILITIES_STRINGBUILDER_H
2 #define CONVERSION_UTILITIES_STRINGBUILDER_H
4 #include "../misc/traits.h"
15 template <
class StringType, Traits::EnableIf<std::is_
class<StringType>> * =
nullptr>
inline std::size_t computeTupleElementSize(
const StringType *str)
20 template <
class StringType, Traits::EnableIf<std::is_
class<StringType>> * =
nullptr>
inline std::size_t computeTupleElementSize(
const StringType &str)
25 template <
class StringType,
class ViewType,
26 Traits::EnableIf<std::is_same<ViewType, std::basic_string_view<typename StringType::value_type>>> * =
nullptr>
27 inline std::size_t computeTupleElementSize(
const ViewType *str)
32 template <
class StringType,
class ViewType,
33 Traits::EnableIf<std::is_same<ViewType, std::basic_string_view<typename StringType::value_type>>> * =
nullptr>
34 inline std::size_t computeTupleElementSize(ViewType str)
39 template <
class StringType,
class CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
40 constexpr std::size_t computeTupleElementSize(
const CharType *str)
42 return std::char_traits<CharType>::length(str);
45 template <
class StringType,
class CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
46 constexpr std::size_t computeTupleElementSize(CharType)
51 template <
class StringType,
typename IntegralType,
52 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
53 std::is_unsigned<IntegralType>> * =
nullptr>
54 constexpr std::size_t computeTupleElementSize(IntegralType number,
typename StringType::value_type base = 10)
57 for (
auto n = number; n; n /= base, ++size)
62 template <
class StringType,
typename IntegralType,
63 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
64 std::is_signed<IntegralType>> * =
nullptr>
65 constexpr std::size_t computeTupleElementSize(IntegralType number,
typename StringType::value_type base = 10)
67 std::size_t size = number < 0 ? 1 : 0;
68 for (
auto n = number; n; n /= base, ++size)
73 template <
class StringType,
typename TupleType, Traits::EnableIf<Traits::IsSpecializationOf<std::decay_t<TupleType>, std::tuple>> * =
nullptr>
74 constexpr std::size_t computeTupleElementSize(TupleType &&tuple,
typename StringType::value_type base = 10);
76 template <
class StringType, Traits::EnableIf<std::is_
class<StringType>> * =
nullptr>
inline void append(StringType &target,
const StringType *str)
81 template <
class StringType, Traits::EnableIf<std::is_
class<StringType>> * =
nullptr>
inline void append(StringType &target,
const StringType &str)
86 template <
class StringType,
class ViewType,
87 Traits::EnableIf<std::is_same<ViewType, std::basic_string_view<typename StringType::value_type>>> * =
nullptr>
88 inline void append(StringType &target,
const ViewType *str)
93 template <
class StringType,
class ViewType,
94 Traits::EnableIf<std::is_same<ViewType, std::basic_string_view<typename StringType::value_type>>> * =
nullptr>
95 inline void append(StringType &target, ViewType str)
100 template <
class StringType,
class CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
101 inline void append(StringType &target,
const CharType *str)
106 template <
class StringType,
class CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
107 inline void append(StringType &target, CharType c)
112 template <
class StringType,
typename IntegralType,
113 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
114 std::is_unsigned<IntegralType>> * =
nullptr>
115 inline void append(StringType &target, IntegralType number,
typename StringType::value_type base = 10)
117 const auto start = target.begin() + target.size();
119 target.insert(start, digitToChar<typename StringType::value_type>(number % base));
124 template <
class StringType,
typename IntegralType,
125 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
126 std::is_signed<IntegralType>> * =
nullptr>
127 inline void append(StringType &target, IntegralType number,
typename StringType::value_type base = 10)
133 const auto start = target.begin() + target.size();
135 target.insert(start, digitToChar<typename StringType::value_type>(number % base));
140 template <
class StringType,
typename TupleType, Traits::EnableIf<Traits::IsSpecializationOf<std::decay_t<TupleType>, std::tuple>> * =
nullptr>
141 constexpr
void append(StringType &target, TupleType &&tuple,
typename StringType::value_type base = 10);
143 template <
class StringType,
class Tuple, std::
size_t N>
struct TupleToString {
144 static inline std::size_t precomputeSize(
const Tuple &tuple)
146 return TupleToString<StringType, Tuple, N - 1>::precomputeSize(tuple) + computeTupleElementSize<StringType>(std::get<N - 1>(tuple));
149 static inline void append(
const Tuple &tuple, StringType &str)
151 TupleToString<StringType, Tuple, N - 1>::append(tuple, str);
152 Helper::append(str, std::get<N - 1>(tuple));
156 template <
class StringType,
class Tuple>
struct TupleToString<StringType, Tuple, 1> {
157 static inline std::size_t precomputeSize(
const Tuple &tuple)
159 return computeTupleElementSize<StringType>(std::get<0>(tuple));
162 static inline void append(
const Tuple &tuple, StringType &str)
164 Helper::append(str, std::get<0>(tuple));
168 template <
class StringType,
typename TupleType, Traits::EnableIf<Traits::IsSpecializationOf<std::decay_t<TupleType>, std::tuple>> *>
169 constexpr std::size_t computeTupleElementSize(TupleType &&tuple,
typename StringType::value_type base)
171 return TupleToString<StringType, TupleType, std::tuple_size_v<std::decay_t<TupleType>>>::precomputeSize(std::forward<TupleType>(tuple));
174 template <
class StringType,
typename TupleType, Traits::EnableIf<Traits::IsSpecializationOf<std::decay_t<TupleType>, std::tuple>> *>
175 constexpr
void append(StringType &target, TupleType &&tuple,
typename StringType::value_type base)
177 return TupleToString<StringType, TupleType, std::tuple_size_v<std::decay_t<TupleType>>>::append(std::forward<TupleType>(tuple), target);
186 template <
class StringType = std::string,
class... Args>
inline StringType
tupleToString(
const std::tuple<Args...> &tuple)
189 res.reserve(Helper::TupleToString<StringType, decltype(tuple),
sizeof...(Args)>::precomputeSize(tuple));
190 Helper::TupleToString<StringType, decltype(tuple),
sizeof...(Args)>::append(tuple, res);
194 template <
class StringType = std::string,
class... Args>
inline StringType
argsToString(Args &&... args)
196 return tupleToString(std::make_tuple(std::forward<Args>(args)...));
202 template <
class Tuple,
class StringType,
203 Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
205 constexpr
auto operator%(
const Tuple &lhs,
const StringType &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
207 return std::tuple_cat(lhs, std::make_tuple(&rhs));
213 template <
class Tuple> constexpr
auto operator%(
const Tuple &lhs,
const char *rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
215 return std::tuple_cat(lhs, std::make_tuple(rhs));
221 template <
class Tuple,
typename IntegralType, Traits::EnableIf<std::is_
integral<IntegralType>> * =
nullptr>
222 constexpr
auto operator%(
const Tuple &lhs, IntegralType rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
224 return std::tuple_cat(lhs, std::make_tuple(rhs));
230 template <
class StringType,
231 Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
233 constexpr
auto operator%(
const StringType &lhs,
const StringType &rhs) -> decltype(std::make_tuple(&lhs, &rhs))
235 return std::make_tuple(&lhs, &rhs);
241 template <
class StringType,
242 Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
244 constexpr
auto operator%(
const char *lhs,
const StringType &rhs) -> decltype(std::make_tuple(lhs, &rhs))
246 return std::make_tuple(lhs, &rhs);
252 template <
class StringType,
253 Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
255 constexpr
auto operator%(
const StringType &lhs,
const char *rhs) -> decltype(std::make_tuple(&lhs, rhs))
257 return std::make_tuple(&lhs, rhs);
263 template <
class StringType,
264 Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
266 constexpr
auto operator%(
const StringType &lhs,
char rhs) -> decltype(std::make_tuple(&lhs, rhs))
268 return std::make_tuple(&lhs, rhs);
274 template <
class StringType,
275 Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
277 constexpr
auto operator%(
char lhs,
const StringType &rhs) -> decltype(std::make_tuple(lhs, &rhs))
279 return std::make_tuple(lhs, &rhs);
291 template <
class Tuple,
class StringType,
292 Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>,
293 Traits::Any<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>>
295 inline std::string
operator+(
const Tuple &lhs,
const StringType &rhs)
297 return tupleToString(std::tuple_cat(lhs, std::make_tuple(&rhs)));
309 template <
class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>> * =
nullptr>
310 inline std::string
operator+(
const Tuple &lhs,
const char *rhs)
312 return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
324 template <
class Tuple,
typename IntegralType,
325 Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>, std::is_integral<IntegralType>> * =
nullptr>
326 inline std::string
operator+(
const Tuple &lhs, IntegralType rhs)
328 return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
332 #endif // CONVERSION_UTILITIES_STRINGBUILDER_H