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 CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
26 constexpr std::size_t computeTupleElementSize(
const CharType *str)
28 return std::char_traits<CharType>::length(str);
31 template <
class StringType,
class CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
32 constexpr std::size_t computeTupleElementSize(CharType)
37 template <
class StringType,
typename IntegralType,
38 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
39 std::is_unsigned<IntegralType>> * =
nullptr>
40 constexpr std::size_t computeTupleElementSize(IntegralType number,
typename StringType::value_type base = 10)
43 for (
auto n = number; n; n /= base, ++size)
48 template <
class StringType,
typename IntegralType,
49 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
50 std::is_signed<IntegralType>> * =
nullptr>
51 constexpr std::size_t computeTupleElementSize(IntegralType number,
typename StringType::value_type base = 10)
53 std::size_t size = number < 0 ? 1 : 0;
54 for (
auto n = number; n; n /= base, ++size)
59 template <
class StringType, Traits::EnableIf<std::is_
class<StringType>> * =
nullptr>
inline void append(StringType &target,
const StringType *str)
64 template <
class StringType, Traits::EnableIf<std::is_
class<StringType>> * =
nullptr>
inline void append(StringType &target,
const StringType &str)
69 template <
class StringType,
class CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
70 inline void append(StringType &target,
const CharType *str)
75 template <
class StringType,
class CharType, Traits::EnableIf<std::is_same<
typename StringType::value_type, CharType>> * =
nullptr>
76 inline void append(StringType &target, CharType c)
81 template <
class StringType,
typename IntegralType,
82 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
83 std::is_unsigned<IntegralType>> * =
nullptr>
84 inline void append(StringType &target, IntegralType number,
typename StringType::value_type base = 10)
86 const auto start = target.begin() + target.size();
88 target.insert(start, digitToChar<typename StringType::value_type>(number % base));
93 template <
class StringType,
typename IntegralType,
94 Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>, std::is_integral<IntegralType>,
95 std::is_signed<IntegralType>> * =
nullptr>
96 inline void append(StringType &target, IntegralType number,
typename StringType::value_type base = 10)
102 const auto start = target.begin() + target.size();
104 target.insert(start, digitToChar<typename StringType::value_type>(number % base));
109 template <
class StringType,
class Tuple, std::
size_t N>
struct TupleToString {
110 static inline std::size_t precomputeSize(
const Tuple &tuple)
112 return TupleToString<StringType, Tuple, N - 1>::precomputeSize(tuple) + computeTupleElementSize<StringType>(std::get<N - 1>(tuple));
115 static inline void append(
const Tuple &tuple, StringType &str)
117 TupleToString<StringType, Tuple, N - 1>::append(tuple, str);
118 Helper::append(str, std::get<N - 1>(tuple));
122 template <
class StringType,
class Tuple>
struct TupleToString<StringType, Tuple, 1> {
123 static inline std::size_t precomputeSize(
const Tuple &tuple)
125 return computeTupleElementSize<StringType>(std::get<0>(tuple));
128 static inline void append(
const Tuple &tuple, StringType &str)
130 Helper::append(str, std::get<0>(tuple));
139 template <
class StringType = std::string,
class... Args>
inline StringType
tupleToString(
const std::tuple<Args...> &tuple)
142 res.reserve(Helper::TupleToString<StringType, decltype(tuple),
sizeof...(Args)>::precomputeSize(tuple));
143 Helper::TupleToString<StringType, decltype(tuple),
sizeof...(Args)>::append(tuple, res);
147 template <
class StringType = std::string,
class... Args>
inline StringType
argsToString(Args &&... args)
149 return tupleToString(std::make_tuple(std::forward<Args>(args)...));
155 template <
class Tuple> constexpr
auto operator%(
const Tuple &lhs,
const std::string &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
157 return std::tuple_cat(lhs, std::make_tuple(&rhs));
163 template <
class Tuple> constexpr
auto operator%(
const Tuple &lhs,
const char *rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
165 return std::tuple_cat(lhs, std::make_tuple(rhs));
171 template <
class Tuple,
typename IntegralType, Traits::EnableIf<std::is_
integral<IntegralType>> * =
nullptr>
172 constexpr
auto operator%(
const Tuple &lhs, IntegralType rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
174 return std::tuple_cat(lhs, std::make_tuple(rhs));
180 constexpr
auto operator%(
const std::string &lhs,
const std::string &rhs) -> decltype(std::make_tuple(&lhs, &rhs))
182 return std::make_tuple(&lhs, &rhs);
188 constexpr
auto operator%(
const char *lhs,
const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
190 return std::make_tuple(lhs, &rhs);
196 constexpr
auto operator%(
const std::string &lhs,
const char *rhs) -> decltype(std::make_tuple(&lhs, rhs))
198 return std::make_tuple(&lhs, rhs);
204 constexpr
auto operator%(
const std::string &lhs,
char rhs) -> decltype(std::make_tuple(&lhs, rhs))
206 return std::make_tuple(&lhs, rhs);
212 constexpr
auto operator%(
char lhs,
const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
214 return std::make_tuple(lhs, &rhs);
226 template <
class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>> * =
nullptr>
227 inline std::string
operator+(
const Tuple &lhs,
const std::string &rhs)
229 return tupleToString(std::tuple_cat(lhs, std::make_tuple(&rhs)));
241 template <
class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>> * =
nullptr>
242 inline std::string
operator+(
const Tuple &lhs,
const char *rhs)
244 return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
256 template <
class Tuple,
typename IntegralType,
257 Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>, std::is_integral<IntegralType>> * =
nullptr>
258 inline std::string
operator+(
const Tuple &lhs, IntegralType rhs)
260 return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
264 #endif // CONVERSION_UTILITIES_STRINGBUILDER_H