C++ Utilities  4.17.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 ConversionUtilities {
11 
13 namespace Helper {
14 
15 template <class StringType, Traits::EnableIf<std::is_class<StringType>> * = nullptr> 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> std::size_t computeTupleElementSize(const StringType &str)
21 {
22  return str.size();
23 }
24 
25 template <class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType>> * = nullptr>
26 std::size_t computeTupleElementSize(const CharType *str)
27 {
28  return std::char_traits<CharType>::length(str);
29 }
30 
31 template <class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType>> * = nullptr>
32 constexpr std::size_t computeTupleElementSize(CharType)
33 {
34  return 1;
35 }
36 
37 template <class StringType, typename IntegralType,
39  std::is_unsigned<IntegralType>> * = nullptr>
40 std::size_t computeTupleElementSize(IntegralType number, typename StringType::value_type base = 10)
41 {
42  std::size_t size = 0;
43  for (auto n = number; n; n /= base, ++size)
44  ;
45  return size;
46 }
47 
48 template <class StringType, typename IntegralType,
50  std::is_signed<IntegralType>> * = nullptr>
51 std::size_t computeTupleElementSize(IntegralType number, typename StringType::value_type base = 10)
52 {
53  std::size_t size = number < 0 ? 1 : 0;
54  for (auto n = number; n; n /= base, ++size)
55  ;
56  return size;
57 }
58 
59 template <class StringType, Traits::EnableIf<std::is_class<StringType>> * = nullptr> void append(StringType &target, const StringType *str)
60 {
61  target.append(*str);
62 }
63 
64 template <class StringType, Traits::EnableIf<std::is_class<StringType>> * = nullptr> void append(StringType &target, const StringType &str)
65 {
66  target.append(str);
67 }
68 
69 template <class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType>> * = nullptr>
70 void append(StringType &target, const CharType *str)
71 {
72  target.append(str);
73 }
74 
75 template <class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType>> * = nullptr>
76 void append(StringType &target, CharType c)
77 {
78  target += c;
79 }
80 
81 template <class StringType, typename IntegralType,
83  std::is_unsigned<IntegralType>> * = nullptr>
84 void append(StringType &target, IntegralType number, typename StringType::value_type base = 10)
85 {
86  const auto start = target.begin() + target.size();
87  do {
88  target.insert(start, digitToChar<typename StringType::value_type>(number % base));
89  number /= base;
90  } while (number);
91 }
92 
93 template <class StringType, typename IntegralType,
95  std::is_signed<IntegralType>> * = nullptr>
96 void append(StringType &target, IntegralType number, typename StringType::value_type base = 10)
97 {
98  if (number < 0) {
99  target += '-';
100  number = -number;
101  }
102  const auto start = target.begin() + target.size();
103  do {
104  target.insert(start, digitToChar<typename StringType::value_type>(number % base));
105  number /= base;
106  } while (number);
107 }
108 
109 template <class StringType, class Tuple, std::size_t N> struct TupleToString {
110  static std::size_t precomputeSize(const Tuple &tuple)
111  {
112  return TupleToString<StringType, Tuple, N - 1>::precomputeSize(tuple) + computeTupleElementSize<StringType>(std::get<N - 1>(tuple));
113  }
114 
115  static void append(const Tuple &tuple, StringType &str)
116  {
117  TupleToString<StringType, Tuple, N - 1>::append(tuple, str);
118  Helper::append(str, std::get<N - 1>(tuple));
119  }
120 };
121 
122 template <class StringType, class Tuple> struct TupleToString<StringType, Tuple, 1> {
123  static std::size_t precomputeSize(const Tuple &tuple)
124  {
125  return computeTupleElementSize<StringType>(std::get<0>(tuple));
126  }
127 
128  static void append(const Tuple &tuple, StringType &str)
129  {
130  Helper::append(str, std::get<0>(tuple));
131  }
132 };
133 } // namespace Helper
135 
139 template <class StringType = std::string, class... Args> StringType tupleToString(const std::tuple<Args...> &tuple)
140 {
141  StringType res;
142  res.reserve(Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::precomputeSize(tuple));
143  Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::append(tuple, res);
144  return res;
145 }
146 
147 template <class StringType = std::string, class... Args> constexpr StringType argsToString(Args &&... args)
148 {
149  return tupleToString(std::make_tuple(args...));
150 }
151 
155 template <class Tuple> constexpr auto operator%(const Tuple &lhs, const std::string &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
156 {
157  return std::tuple_cat(lhs, std::make_tuple(&rhs));
158 }
159 
163 template <class Tuple> constexpr auto operator%(const Tuple &lhs, const char *rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
164 {
165  return std::tuple_cat(lhs, std::make_tuple(rhs));
166 }
167 
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)))
173 {
174  return std::tuple_cat(lhs, std::make_tuple(rhs));
175 }
176 
180 constexpr auto operator%(const std::string &lhs, const std::string &rhs) -> decltype(std::make_tuple(&lhs, &rhs))
181 {
182  return std::make_tuple(&lhs, &rhs);
183 }
184 
188 constexpr auto operator%(const char *lhs, const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
189 {
190  return std::make_tuple(lhs, &rhs);
191 }
192 
196 constexpr auto operator%(const std::string &lhs, const char *rhs) -> decltype(std::make_tuple(&lhs, rhs))
197 {
198  return std::make_tuple(&lhs, rhs);
199 }
200 
204 constexpr auto operator%(const std::string &lhs, char rhs) -> decltype(std::make_tuple(&lhs, rhs))
205 {
206  return std::make_tuple(&lhs, rhs);
207 }
208 
212 constexpr auto operator%(char lhs, const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
213 {
214  return std::make_tuple(lhs, &rhs);
215 }
216 
226 template <class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>> * = nullptr>
227 inline std::string operator+(const Tuple &lhs, const std::string &rhs)
228 {
229  return tupleToString(std::tuple_cat(lhs, std::make_tuple(&rhs)));
230 }
231 
241 template <class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>> * = nullptr>
242 inline std::string operator+(const Tuple &lhs, const char *rhs)
243 {
244  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
245 }
246 
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)
259 {
260  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
261 }
262 } // namespace ConversionUtilities
263 
264 #endif // CONVERSION_UTILITIES_STRINGBUILDER_H
constexpr StringType argsToString(Args &&... args)
typename std::enable_if< All< Condition... >::value, Detail::Enabler >::type EnableIf
Shortcut for std::enable_if to omit ::value and ::type.
Definition: traits.h:48
Contains several functions providing conversions between different data types.
constexpr auto operator%(const Tuple &lhs, const std::string &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
Allows construction of string-tuples via %-operator, eg.
std::string operator+(const Tuple &lhs, const std::string &rhs)
Allows construction of final string from previously constructed string-tuple and trailing string via ...
StringType tupleToString(const std::tuple< Args... > &tuple)
Concatenates all strings hold by the specified tuple.