C++ Utilities  4.9.1
Common C++ classes and routines used by my applications 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>>...> std::size_t computeTupleElementSize(const StringType *str)
16 {
17  return str->size();
18 }
19 
20 template <class StringType, Traits::EnableIf<std::is_class<StringType>>...> 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>>...>
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>>...>
32 constexpr std::size_t computeTupleElementSize(CharType)
33 {
34  return 1;
35 }
36 
37 template <class StringType, typename IntegralType, Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>,
38  std::is_integral<IntegralType>, std::is_unsigned<IntegralType>>...>
39 std::size_t computeTupleElementSize(IntegralType number, typename StringType::value_type base = 10)
40 {
41  std::size_t size = 0;
42  for (auto n = number; n; n /= base, ++size)
43  ;
44  return size;
45 }
46 
47 template <class StringType, typename IntegralType, Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>,
48  std::is_integral<IntegralType>, std::is_signed<IntegralType>>...>
49 std::size_t computeTupleElementSize(IntegralType number, typename StringType::value_type base = 10)
50 {
51  std::size_t size = number < 0 ? 1 : 0;
52  for (auto n = number; n; n /= base, ++size)
53  ;
54  return size;
55 }
56 
57 template <class StringType, Traits::EnableIf<std::is_class<StringType>>...> void append(StringType &target, const StringType *str)
58 {
59  target.append(*str);
60 }
61 
62 template <class StringType, Traits::EnableIf<std::is_class<StringType>>...> void append(StringType &target, const StringType &str)
63 {
64  target.append(str);
65 }
66 
67 template <class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType>>...>
68 void append(StringType &target, const CharType *str)
69 {
70  target.append(str);
71 }
72 
73 template <class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType>>...>
74 void append(StringType &target, CharType c)
75 {
76  target += c;
77 }
78 
79 template <class StringType, typename IntegralType, Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>,
80  std::is_integral<IntegralType>, std::is_unsigned<IntegralType>>...>
81 void append(StringType &target, IntegralType number, typename StringType::value_type base = 10)
82 {
83  const auto start = target.begin() + target.size();
84  do {
85  target.insert(start, digitToChar<typename StringType::value_type>(number % base));
86  number /= base;
87  } while (number);
88 }
89 
90 template <class StringType, typename IntegralType, Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType>>,
91  std::is_integral<IntegralType>, std::is_signed<IntegralType>>...>
92 void append(StringType &target, IntegralType number, typename StringType::value_type base = 10)
93 {
94  if (number < 0) {
95  target += '-';
96  number = -number;
97  }
98  const auto start = target.begin() + target.size();
99  do {
100  target.insert(start, digitToChar<typename StringType::value_type>(number % base));
101  number /= base;
102  } while (number);
103 }
104 
105 template <class StringType, class Tuple, std::size_t N> struct TupleToString {
106  static std::size_t precomputeSize(const Tuple &tuple)
107  {
108  return TupleToString<StringType, Tuple, N - 1>::precomputeSize(tuple) + computeTupleElementSize<StringType>(std::get<N - 1>(tuple));
109  }
110 
111  static void append(const Tuple &tuple, StringType &str)
112  {
113  TupleToString<StringType, Tuple, N - 1>::append(tuple, str);
114  Helper::append(str, std::get<N - 1>(tuple));
115  }
116 };
117 
118 template <class StringType, class Tuple> struct TupleToString<StringType, Tuple, 1> {
119  static std::size_t precomputeSize(const Tuple &tuple)
120  {
121  return computeTupleElementSize<StringType>(std::get<0>(tuple));
122  }
123 
124  static void append(const Tuple &tuple, StringType &str)
125  {
126  Helper::append(str, std::get<0>(tuple));
127  }
128 };
129 }
131 
135 template <class StringType = std::string, class... Args> StringType tupleToString(const std::tuple<Args...> &tuple)
136 {
137  StringType res;
138  res.reserve(Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::precomputeSize(tuple));
139  Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::append(tuple, res);
140  return res;
141 }
142 
143 template <class StringType = std::string, class... Args> constexpr StringType argsToString(Args &&... args)
144 {
145  return tupleToString(std::make_tuple(args...));
146 }
147 
151 template <class Tuple> constexpr auto operator%(const Tuple &lhs, const std::string &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
152 {
153  return std::tuple_cat(lhs, std::make_tuple(&rhs));
154 }
155 
159 template <class Tuple> constexpr auto operator%(const Tuple &lhs, const char *rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
160 {
161  return std::tuple_cat(lhs, std::make_tuple(rhs));
162 }
163 
167 template <class Tuple, typename IntegralType, Traits::EnableIf<std::is_integral<IntegralType>>...>
168 constexpr auto operator%(const Tuple &lhs, IntegralType rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
169 {
170  return std::tuple_cat(lhs, std::make_tuple(rhs));
171 }
172 
176 constexpr auto operator%(const std::string &lhs, const std::string &rhs) -> decltype(std::make_tuple(&lhs, &rhs))
177 {
178  return std::make_tuple(&lhs, &rhs);
179 }
180 
184 constexpr auto operator%(const char *lhs, const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
185 {
186  return std::make_tuple(lhs, &rhs);
187 }
188 
192 constexpr auto operator%(const std::string &lhs, const char *rhs) -> decltype(std::make_tuple(&lhs, rhs))
193 {
194  return std::make_tuple(&lhs, rhs);
195 }
196 
200 constexpr auto operator%(const std::string &lhs, char rhs) -> decltype(std::make_tuple(&lhs, rhs))
201 {
202  return std::make_tuple(&lhs, rhs);
203 }
204 
208 constexpr auto operator%(char lhs, const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
209 {
210  return std::make_tuple(lhs, &rhs);
211 }
212 
222 template <class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>>...>
223 inline std::string operator+(const Tuple &lhs, const std::string &rhs)
224 {
225  return tupleToString(std::tuple_cat(lhs, std::make_tuple(&rhs)));
226 }
227 
237 template <class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>>...>
238 inline std::string operator+(const Tuple &lhs, const char *rhs)
239 {
240  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
241 }
242 
252 template <class Tuple, typename IntegralType, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>, std::is_integral<IntegralType>>...>
253 inline std::string operator+(const Tuple &lhs, IntegralType rhs)
254 {
255  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
256 }
257 }
258 
259 #endif // CONVERSION_UTILITIES_STRINGBUILDER_H
constexpr StringType argsToString(Args &&... args)
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.