C++ Utilities  4.6.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 "./stringconversion.h"
5 #include "../misc/traits.h"
6 
7 #include <string>
8 #include <tuple>
9 
10 namespace ConversionUtilities
11 {
12 
14 namespace Helper {
15 
16 template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
17 std::size_t computeTupleElementSize(const StringType *str)
18 {
19  return str->size();
20 }
21 
22 template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
23 std::size_t computeTupleElementSize(const StringType &str)
24 {
25  return str.size();
26 }
27 
28 template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
29 std::size_t computeTupleElementSize(const CharType *str)
30 {
31  return std::char_traits<CharType>::length(str);
32 }
33 
34 template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
35 constexpr std::size_t computeTupleElementSize(CharType)
36 {
37  return 1;
38 }
39 
40 template <class StringType, typename IntegralType, Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType> >, std::is_integral<IntegralType>, std::is_unsigned<IntegralType> >...>
41 std::size_t computeTupleElementSize(IntegralType number, typename StringType::value_type base = 10)
42 {
43  std::size_t size = 0;
44  for(auto n = number; n; n /= base, ++size);
45  return size;
46 }
47 
48 template <class StringType, typename IntegralType, Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType> >, 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  return size;
54 }
55 
56 template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
57 void append(StringType &target, const StringType *str)
58 {
59  target.append(*str);
60 }
61 
62 template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
63 void append(StringType &target, const StringType &str)
64 {
65  target.append(str);
66 }
67 
68 template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
69 void append(StringType &target, const CharType *str)
70 {
71  target.append(str);
72 }
73 
74 template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
75 void append(StringType &target, CharType c)
76 {
77  target += c;
78 }
79 
80 template <class StringType, typename IntegralType, Traits::EnableIf<Traits::Not<std::is_same<typename StringType::value_type, IntegralType> >, 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> >, std::is_integral<IntegralType>, std::is_signed<IntegralType> >...>
91 void append(StringType &target, IntegralType number, typename StringType::value_type base = 10)
92 {
93  if(number < 0) {
94  target += '-';
95  number = -number;
96  }
97  const auto start = target.begin() + target.size();
98  do {
99  target.insert(start, digitToChar<typename StringType::value_type>(number % base));
100  number /= base;
101  } while(number);
102 }
103 
104 template<class StringType, class Tuple, std::size_t N>
105 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>
119 struct TupleToString<StringType, Tuple, 1> {
120  static std::size_t precomputeSize(const Tuple &tuple)
121  {
122  return computeTupleElementSize<StringType>(std::get<0>(tuple));
123  }
124 
125  static void append(const Tuple &tuple, StringType &str)
126  {
127  Helper::append(str, std::get<0>(tuple));
128  }
129 };
130 
131 }
133 
137 template<class StringType = std::string, class... Args>
138 StringType tupleToString(const std::tuple<Args...> &tuple)
139 {
140  StringType res;
141  res.reserve(Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::precomputeSize(tuple));
142  Helper::TupleToString<StringType, decltype(tuple), sizeof...(Args)>::append(tuple, res);
143  return res;
144 }
145 
146 template<class StringType = std::string, class... Args>
147 constexpr StringType argsToString(Args&&... args)
148 {
149  return tupleToString(std::make_tuple(args...));
150 }
151 
155 template<class Tuple>
156 constexpr auto operator %(const Tuple &lhs, const std::string &rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(&rhs)))
157 {
158  return std::tuple_cat(lhs, std::make_tuple(&rhs));
159 }
160 
164 template<class Tuple>
165 constexpr auto operator %(const Tuple &lhs, const char *rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
166 {
167  return std::tuple_cat(lhs, std::make_tuple(rhs));
168 }
169 
173 template<class Tuple, typename IntegralType, Traits::EnableIf<std::is_integral<IntegralType> >...>
174 constexpr auto operator %(const Tuple &lhs, IntegralType rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
175 {
176  return std::tuple_cat(lhs, std::make_tuple(rhs));
177 }
178 
182 constexpr auto operator %(const std::string &lhs, const std::string &rhs) -> decltype(std::make_tuple(&lhs, &rhs))
183 {
184  return std::make_tuple(&lhs, &rhs);
185 }
186 
190 constexpr auto operator %(const char *lhs, const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
191 {
192  return std::make_tuple(lhs, &rhs);
193 }
194 
198 constexpr auto operator %(const std::string &lhs, const char *rhs) -> decltype(std::make_tuple(&lhs, rhs))
199 {
200  return std::make_tuple(&lhs, rhs);
201 }
202 
206 constexpr auto operator %(const std::string &lhs, char rhs) -> decltype(std::make_tuple(&lhs, rhs))
207 {
208  return std::make_tuple(&lhs, rhs);
209 }
210 
214 constexpr auto operator %(char lhs, const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs))
215 {
216  return std::make_tuple(lhs, &rhs);
217 }
218 
228 template<class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple> >...>
229 inline std::string operator +(const Tuple &lhs, const std::string &rhs)
230 {
231  return tupleToString(std::tuple_cat(lhs, std::make_tuple(&rhs)));
232 }
233 
243 template<class Tuple, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple> >...>
244 inline std::string operator +(const Tuple &lhs, const char *rhs)
245 {
246  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
247 }
248 
258 template<class Tuple, typename IntegralType, Traits::EnableIf<Traits::IsSpecializationOf<Tuple, std::tuple>, std::is_integral<IntegralType> >...>
259 inline std::string operator +(const Tuple &lhs, IntegralType rhs)
260 {
261  return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
262 }
263 
264 }
265 
266 #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.