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 
44 std::deque<std::string> split(const std::string& s, const char delimiter) {
45  std::deque<std::string> tokens;
46 
47  if(s.length() == 0) {
48  return tokens;
49  }
50 
51  size_t i = 0;
52  while(i < s.size()) {
53  size_t k = s.find(delimiter, i);
54 
55  if(k == std::string::npos) {
56  tokens.push_back(s.substr(i,std::string::npos));
57  return tokens;
58  }
59  else {
60  tokens.push_back(s.substr(i,k-i));
61  i=k+1;
62  }
63  }
64 
65  // if we get here, that means that the last found k was the last
66  // character, which means we need to append ""
67  tokens.push_back("");
68  return tokens;
69 }
70 
77 template<size_t N>
78 std::array<std::string, N> split(const std::string& s, const char delimiter) {
79  std::array<std::string, N> out;
80 
81  auto q = split(s, delimiter);
82 
83  // must be the right size
84  if(q.size() != N) {
85  std::cerr << "*** String in split<N> has " << q.size() << " not " << N << " elements: " << s << std::endl;
86  assert(false);
87  }
88 
89  // convert to an array now that we know it's the right size
90  size_t i = 0;
91  for(auto& x : q) {
92  out[i++] = x;
93  }
94 
95  return out;
96 }
97 
103 template<typename T>
104 std::string str(T x){
105 
106  // special handling of a few key types:
107  if constexpr (std::is_pointer<T>::value) {
108  std::ostringstream address;
109  address << (void const *)x;
110  return address.str();
111  }
112  else if constexpr(std::is_same<T,char>::value) {
113  return std::string(1,x);
114  }
115  else if constexpr(has_string<T>::value) {
116  return x.string();
117  }
118  else {
119  return std::to_string(x);
120  }
121 }
122 
123 std::string str(const std::string& x){
124  // Need to specialize this, otherwise std::to_string fails
125  return x;
126 }
127 
128 template<typename... T, size_t... I >
129 std::string str(const std::tuple<T...>& x, std::index_sequence<I...> idx){
135  return "<" + ( (std::to_string(std::get<I>(x)) + ",") + ...) + ">";
136 }
137 template<typename... T>
138 std::string str(const std::tuple<T...>& x ){
144  return str(x, std::make_index_sequence<sizeof...(T)>() );
145 }
146 
147 template<typename A, typename B >
148 std::string str(const std::pair<A,B> x){
154  return "<" + str(x.first) + "," + str(x.second) + ">";
155 }
156 
157 template<typename T, size_t N>
158 std::string str(const std::array<T, N>& a ){
164  std::string out = "<";
165  for(auto& x : a) {
166  out += str(x) + ",";
167  }
168 
169  if(a.size()>0)
170  out.erase(out.size()-1); // remove that last dumb comma
171 
172  return out+">";
173 }
174 
175 
176 template<typename T>
177 std::string str(const std::vector<T>& a, const std::string _sep=","){
183  std::string out = "[";
184  for(const auto& x : a) {
185  out += str(x) + _sep;
186  }
187  if(a.size()>0)
188  out.erase(out.size()-1); // remove that last dumb comma
189 
190  return out+"]";
191 }
192 
193 template<typename T, typename U>
194 std::string str(const std::map<T,U>& a ){
200  std::string out = "{";
201  for(auto& x : a) {
202  out += str(x.first) + ":" + str(x.second) + ",";
203  }
204  if(a.size()>0)
205  out.erase(out.size()-1); // remove that last dumb comma
206  out += "}";
207 
208  return out;
209 }
210 
211 template<typename T>
212 std::string str(const std::set<T>& a ){
218  std::string out = "{";
219  for(auto& x : a) {
220  out += str(x)+",";
221  }
222  if(a.size()>0)
223  out.erase(out.size()-1); // remove that last dumb comma
224  out += "}";
225 
226  return out;
227 }
228 
229 
230 template<typename T>
231 std::string str(const std::atomic<T>& a ){
237  return str(a.load());
238 }
239 
240 
241 template<typename... Args>
242 std::string str(std::string _sep, Args... args){
243 
244  std::string out = "";
245  ((out += str(args)+_sep), ...);
246 
247  // at the end of this we have one extra sep, so let's delete it
248  out.erase(out.size()-_sep.size());
249 
250  return out;
251 }
252 
253 
254 
263 template<typename T>
264 T string_to(const std::string s) {
265 
266  // process some special cases here
268  T m;
269  for(auto& r : split(s, ',')) { // TODO might want a diff delim here
270  auto [x, y] = split<2>(r, ':');
271  m[string_to<typename T::key_type>(x)] = string_to<typename T::mapped_type>(y);
272  }
273  return m;
274  }
276  auto [x,y] = split<2>(s, ':');
277  return {string_to<typename T::first_type>(x), string_to<typename T::second_type>(y)};
278  }
279  else if constexpr(is_specialization<T,std::vector>::value) {
280  T v;
281  for(auto& x : split(s, ',')) {
282  v.push_back(string_to<typename T::value_type>(x));
283  }
284  return v;
285  }
286  else if constexpr(is_specialization<T,std::multiset>::value) {
287  T ret;
288  for(auto& x : split(s, ',')) {
289  ret.insert( string_to<typename T::key_type>(x));
290  }
291  return ret;
292  }
293  else {
294  // Otherwise we must have a string constructor
295  return T{s};
296  }
297 }
298 
299 template<> std::string string_to(const std::string s) { return s; }
300 template<> int string_to(const std::string s) { return std::stoi(s); }
301 template<> long string_to(const std::string s) { return std::stol(s); }
302 template<> unsigned long string_to(const std::string s) { return std::stoul(s); }
303 template<> double string_to(const std::string s) { return std::stod(s); }
304 template<> float string_to(const std::string s) { return std::stof(s); }
305 template<> bool string_to(const std::string s) { assert(s.size()==1); return s=="1"; } // 0/1 for t/f
306 
307 //template<typename T, typename U>
308 //std::pair<T,U> string_to(const std::string s) {
309 // auto [x,y] = split<2>(s, ':');
310 // return {string_to<T>(x), string_to<U>(y)};
311 //}
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:44
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:264
std::string str(T x)
A pythonesque string function. This gets specialized in many ways.
Definition: str.h:104
Check if a type is contained in parameter pack // *.
Definition: Miscellaneous.h:137
Definition: str.h:20