C++ Utilities  5.2.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
stringbuilder.h
Go to the documentation of this file.
1 #ifndef CONVERSION_UTILITIES_STRINGBUILDER_H
2 #define CONVERSION_UTILITIES_STRINGBUILDER_H
3 
4 #include "../misc/traits.h"
5 #include "./stringconversion.h"
6 
7 #include <string>
8 #include <tuple>
9 
10 namespace CppUtilities {
11 
13 namespace Helper {
14 
15 template <class StringType, Traits::EnableIf<std::is_class<StringType>> * = nullptr> inline std::size_t computeTupleElementSize(const StringType *str)
16 {
17  return str->size();
18 }
19 
20 template <class StringType, Traits::EnableIf<std::is_class<StringType>> * = nullptr> inline std::size_t computeTupleElementSize(const StringType &str)
21 {
22  return str.size();
23 }
24 
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)
28 {
29  return str->size();
30 }
31 
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)
35 {
36  return str.size();
37 }
38 
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)
41 {
42  return std::char_traits<CharType>::length(str);
43 }
44 
45 template <class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType>> * = nullptr>
46 constexpr std::size_t computeTupleElementSize(CharType)
47 {
48  return 1;
49 }
50 
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)
55 {
56  std::size_t size = 0;
57  for (auto n = number; n; n /= base, ++size)
58  ;
59  return size;
60 }
61 
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)
66 {
67  std::size_t size = number < 0 ? 1 : 0;
68  for (auto n = number; n; n /= base, ++size)
69  ;
70  return size;
71 }
72 
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);
75 
76 template <class StringType, Traits::EnableIf<std::is_class<StringType>> * = nullptr> inline void append(StringType &target, const StringType *str)
77 {
78  target.append(*str);
79 }
80 
81 template <class StringType, Traits::EnableIf<std::is_class<StringType>> * = nullptr> inline void append(StringType &target, const StringType &str)
82 {
83  target.append(str);
84 }
85 
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)
89 {
90  target.append(*str);
91 }
92 
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)
96 {
97  target.append(str);
98 }
99 
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)
102 {
103  target.append(str);
104 }
105 
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)
108 {
109  target += c;
110 }
111 
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)
116 {
117  const auto start = target.begin() + target.size();
118  do {
119  target.insert(start, digitToChar<typename StringType::value_type>(number % base));
120  number /= base;
121  } while (number);
122 }
123 
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)
128 {
129  if (number < 0) {
130  target += '-';
131  number = -number;
132  }
133  const auto start = target.begin() + target.size();
134  do {
135  target.insert(start, digitToChar<typename StringType::value_type>(number % base));
136  number /= base;
137  } while (number);
138 }
139 
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);
142 
143 template <class StringType, class Tuple, std::size_t N> struct TupleToString {
144  static inline std::size_t precomputeSize(const Tuple &tuple)
145  {
146  return TupleToString<StringType, Tuple, N - 1>::precomputeSize(tuple) + computeTupleElementSize<StringType>(std::get<N - 1>(tuple));
147  }
148 
149  static inline void append(const Tuple &tuple, StringType &str)
150  {
151  TupleToString<StringType, Tuple, N - 1>::append(tuple, str);
152  Helper::append(str, std::get<N - 1>(tuple));
153  }
154 };
155 
156 template <class StringType, class Tuple> struct TupleToString<StringType, Tuple, 1> {
157  static inline std::size_t precomputeSize(const Tuple &tuple)
158  {
159  return computeTupleElementSize<StringType>(std::get<0>(tuple));
160  }
161 
162  static inline void append(const Tuple &tuple, StringType &str)
163  {
164  Helper::append(str, std::get<0>(tuple));
165  }
166 };
167 
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)
170 {
171  return TupleToString<StringType, TupleType, std::tuple_size_v<std::decay_t<TupleType>>>::precomputeSize(std::forward<TupleType>(tuple));
172 }
173 
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)
176 {
177  return TupleToString<StringType, TupleType, std::tuple_size_v<std::decay_t<TupleType>>>::append(std::forward<TupleType>(tuple), target);
178 }
179 
180 } // namespace Helper
182 
186 template <class StringType = std::string, class... Args> inline StringType tupleToString(const std::tuple<Args...> &tuple)
187 {
188  StringType res;
189  res.reserve(Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::precomputeSize(tuple));
190  Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::append(tuple, res);
191  return res;
192 }
193 
194 template <class StringType = std::string, class... Args> inline StringType argsToString(Args &&... args)
195 {
196  return tupleToString(std::make_tuple(std::forward<Args>(args)...));
197 }
198 
202 template <class Tuple, class StringType,
203  Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
204  * = nullptr>
205 constexpr auto operator%(const Tuple &lhs, const StringType &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
206 {
207  return std::tuple_cat(lhs, std::make_tuple(&rhs));
208 }
209 
213 template <class Tuple> constexpr auto operator%(const Tuple &lhs, const char *rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
214 {
215  return std::tuple_cat(lhs, std::make_tuple(rhs));
216 }
217 
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)))
223 {
224  return std::tuple_cat(lhs, std::make_tuple(rhs));
225 }
226 
230 template <class StringType,
231  Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
232  * = nullptr>
233 constexpr auto operator%(const StringType &lhs, const StringType &rhs) -> decltype(std::make_tuple(&lhs, &rhs))
234 {
235  return std::make_tuple(&lhs, &rhs);
236 }
237 
241 template <class StringType,
242  Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
243  * = nullptr>
244 constexpr auto operator%(const char *lhs, const StringType &rhs) -> decltype(std::make_tuple(lhs, &rhs))
245 {
246  return std::make_tuple(lhs, &rhs);
247 }
248 
252 template <class StringType,
253  Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
254  * = nullptr>
255 constexpr auto operator%(const StringType &lhs, const char *rhs) -> decltype(std::make_tuple(&lhs, rhs))
256 {
257  return std::make_tuple(&lhs, rhs);
258 }
259 
263 template <class StringType,
264  Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
265  * = nullptr>
266 constexpr auto operator%(const StringType &lhs, char rhs) -> decltype(std::make_tuple(&lhs, rhs))
267 {
268  return std::make_tuple(&lhs, rhs);
269 }
270 
274 template <class StringType,
275  Traits::EnableIfAny<Traits::IsSpecializationOf<StringType, std::basic_string>, Traits::IsSpecializationOf<StringType, std::basic_string_view>>
276  * = nullptr>
277 constexpr auto operator%(char lhs, const StringType &rhs) -> decltype(std::make_tuple(lhs, &rhs))
278 {
279  return std::make_tuple(lhs, &rhs);
280 }
281 
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>>>
294  * = nullptr>
295 inline std::string operator+(const Tuple &lhs, const StringType &rhs)
296 {
297  return tupleToString(std::tuple_cat(lhs, std::make_tuple(&rhs)));
298 }
299 
309 template <class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>> * = nullptr>
310 inline std::string operator+(const Tuple &lhs, const char *rhs)
311 {
312  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
313 }
314 
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)
327 {
328  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
329 }
330 } // namespace CppUtilities
331 
332 #endif // CONVERSION_UTILITIES_STRINGBUILDER_H
stringconversion.h
CppUtilities::operator+
CPP_UTILITIES_EXPORT DateTime operator+(DateTime begin, Period period)
Adds the specified period to the specified date.
Definition: period.cpp:60
CppUtilities::operator%
constexpr auto operator%(const Tuple &lhs, const StringType &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
Allows construction of string-tuples via %-operator, eg.
Definition: stringbuilder.h:205
CppUtilities::argsToString
StringType argsToString(Args &&... args)
Definition: stringbuilder.h:194
CppUtilities
Contains all utilities provides by the c++utilities library.
Definition: argumentparser.h:17
CppUtilities::tupleToString
StringType tupleToString(const std::tuple< Args... > &tuple)
Concatenates all strings hold by the specified tuple.
Definition: stringbuilder.h:186