Fleet  0.0.9
Inference in the LOT
str.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <sstream>
4 #include <queue>
5 #include <array>
6 #include <map>
7 #include <set>
8 #include <atomic>
9 #include <string>
10 
11 
19 template <typename T>
21 {
22  typedef char one;
23  struct two { char x[2]; };
24 
25  template <typename C> static one test( decltype(&C::string) ) ;
26  template <typename C> static two test(...);
27 
28 public:
29  enum { value = sizeof(test<T>(0)) == sizeof(char) };
30 };
31 
32 
33 
34 // This is thrown by split when it has the wrong number of things
35 // allowing us to recover from lines that are bad
36 struct StringSplitException : public std::exception {
37 
38 };
39 
50 std::deque<std::string> split(const std::string& s, const char delimiter) {
51  std::deque<std::string> tokens;
52 
53  if(s.length() == 0) {
54  return tokens;
55  }
56 
57  size_t i = 0;
58  while(i < s.size()) {
59  size_t k = s.find(delimiter, i);
60 
61  if(k == std::string::npos) {
62  tokens.push_back(s.substr(i,std::string::npos));
63  return tokens;
64  }
65  else {
66  tokens.push_back(s.substr(i,k-i));
67  i=k+1;
68  }
69  }
70 
71  // if we get here, that means that the last found k was the last
72  // character, which means we need to append ""
73  tokens.push_back("");
74  return tokens;
75 }
76 
83 template<size_t N>
84 std::array<std::string, N> split(const std::string& s, const char delimiter) {
85  std::array<std::string, N> out;
86 
87  auto q = split(s, delimiter);
88 
89  // must be the right size
90  if(q.size() != N) {
91  std::cerr << "*** String in split<N> has " << q.size() << " not " << N << " elements: " << s << std::endl;
92  throw StringSplitException();
93  }
94 
95  // convert to an array now that we know it's the right size
96  size_t i = 0;
97  for(auto& x : q) {
98  out[i++] = x;
99  }
100 
101  return out;
102 }
103 
109 template<typename T>
110 std::string str(T x){
111 
112  // special handling of a few key types:
113  if constexpr (std::is_pointer<T>::value) {
114  std::ostringstream address;
115  address << (void const *)x;
116  return address.str();
117  }
118  else if constexpr(std::is_same<T,char>::value) {
119  return std::string(1,x);
120  }
121  else if constexpr(has_string<T>::value) {
122  return x.string();
123  }
124  else {
125  return std::to_string(x);
126  }
127 }
128 
129 std::string str(const std::string& x){
130  // Need to specialize this, otherwise std::to_string fails
131  return x;
132 }
133 
134 template<typename... T, size_t... I >
135 std::string str(const std::tuple<T...>& x, std::index_sequence<I...> idx){
141  return "<" + ( (std::to_string(std::get<I>(x)) + ",") + ...) + ">";
142 }
143 template<typename... T>
144 std::string str(const std::tuple<T...>& x ){
150  return str(x, std::make_index_sequence<sizeof...(T)>() );
151 }
152 
153 template<typename A, typename B >
154 std::string str(const std::pair<A,B> x){
160  return "<" + str(x.first) + "," + str(x.second) + ">";
161 }
162 
163 template<typename T, size_t N>
164 std::string str(const std::array<T, N>& a ){
170  std::string out = "<";
171  for(auto& x : a) {
172  out += str(x) + ",";
173  }
174 
175  if(a.size()>0)
176  out.erase(out.size()-1); // remove that last dumb comma
177 
178  return out+">";
179 }
180 
181 
182 template<typename T>
183 std::string str(const std::vector<T>& a, const std::string _sep=","){
189  std::string out = "[";
190  for(const auto& x : a) {
191  out += str(x) + _sep;
192  }
193  if(a.size()>0)
194  out.erase(out.size()-1); // remove that last dumb comma
195 
196  return out+"]";
197 }
198 
199 template<typename T, typename U>
200 std::string str(const std::map<T,U>& a ){
206  std::string out = "{";
207  for(auto& x : a) {
208  out += str(x.first) + ":" + str(x.second) + ",";
209  }
210  if(a.size()>0)
211  out.erase(out.size()-1); // remove that last dumb comma
212  out += "}";
213 
214  return out;
215 }
216 
217 template<typename T>
218 std::string str(const std::set<T>& a ){
224  std::string out = "{";
225  for(auto& x : a) {
226  out += str(x)+",";
227  }
228  if(a.size()>0)
229  out.erase(out.size()-1); // remove that last dumb comma
230  out += "}";
231 
232  return out;
233 }
234 
235 
236 template<typename T>
237 std::string str(const std::atomic<T>& a ){
243  return str(a.load());
244 }
245 
246 
247 template<typename... Args>
248 std::string str(std::string _sep, Args... args){
249 
250  std::string out = "";
251  ((out += str(args)+_sep), ...);
252 
253  // at the end of this we have one extra sep, so let's delete it
254  out.erase(out.size()-_sep.size());
255 
256  return out;
257 }
258 
259 
260 
269 template<typename T>
270 T string_to(const std::string s) {
271 
272  // process some special cases here
274  T m;
275  for(auto& r : split(s, ',')) { // TODO might want a diff delim here
276  auto [x, y] = split<2>(r, ':');
277  m[string_to<typename T::key_type>(x)] = string_to<typename T::mapped_type>(y);
278  }
279  return m;
280  }
282  auto [x,y] = split<2>(s, ':');
283  return {string_to<typename T::first_type>(x), string_to<typename T::second_type>(y)};
284  }
285  else if constexpr(is_specialization<T,std::vector>::value) {
286  T v;
287  for(auto& x : split(s, ',')) {
288  v.push_back(string_to<typename T::value_type>(x));
289  }
290  return v;
291  }
292  else if constexpr(is_specialization<T,std::multiset>::value) {
293  T ret;
294  for(auto& x : split(s, ',')) {
295  ret.insert( string_to<typename T::key_type>(x));
296  }
297  return ret;
298  }
299  else {
300  // Otherwise we must have a string constructor
301  return T{s};
302  }
303 }
304 
305 template<> std::string string_to(const std::string s) { return s; }
306 template<> int string_to(const std::string s) { return std::stoi(s); }
307 template<> long string_to(const std::string s) { return std::stol(s); }
308 template<> unsigned long string_to(const std::string s) { return std::stoul(s); }
309 template<> double string_to(const std::string s) { return std::stod(s); }
310 template<> float string_to(const std::string s) { return std::stof(s); }
311 template<> bool string_to(const std::string s) { assert(s.size()==1); return s=="1"; } // 0/1 for t/f
312 
313 //template<typename T, typename U>
314 //std::pair<T,U> string_to(const std::string s) {
315 // auto [x,y] = split<2>(s, ':');
316 // return {string_to<T>(x), string_to<U>(y)};
317 //}
Definition: str.h:29
std::deque< std::string > split(const std::string &s, const char delimiter)
Split is returns a deque of s split up at the character delimiter. It handles these special cases: sp...
Definition: str.h:50
T string_to(const std::string s)
Fleet includes this templated function to allow us to convert strings to a variety of formats...
Definition: str.h:270
std::string str(T x)
A pythonesque string function. This gets specialized in many ways.
Definition: str.h:110
Check if a type is contained in parameter pack // *.
Definition: Miscellaneous.h:137
Definition: str.h:36
Definition: str.h:20