OmniSciDB  21ac014ffc
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
toString.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  This header file provides the following C++ template functions:
19 
20  toString(const T& v) -> std::string
21 
22  Convert object v of type T to string. Pretty-printing is
23  enabled for objects that types define `toString` or `to_string`
24  methods.
25 
26  typeName(const T* v) -> std::string
27 
28  Return the type name of an object passed in via its pointer
29  value.
30 
31  and a convenience macro `PRINT(EXPR)` that sends the string
32  representation of any expression to stdout.
33 */
34 
35 #pragma once
36 
37 #ifndef __CUDACC__
38 
39 #define HAVE_TOSTRING
40 
41 #ifndef _WIN32
42 #include <cxxabi.h>
43 #endif
44 
45 #include <chrono>
46 #include <iostream>
47 #include <set>
48 #include <sstream>
49 #include <tuple>
50 #include <type_traits>
51 #include <unordered_map>
52 #include <unordered_set>
53 #include <vector>
54 #include "sqldefs.h"
55 
56 #ifdef ENABLE_TOSTRING_RAPIDJSON
57 #if __has_include(<rapidjson/document.h> )
58 #include <rapidjson/document.h>
59 #include <rapidjson/stringbuffer.h>
60 #include <rapidjson/writer.h>
61 #else
62 #undefine ENABLE_TOSTRING_RAPIDJSON
63 #endif
64 #endif
65 
66 #ifdef ENABLE_TOSTRING_LLVM
67 #if __has_include(<llvm/Support/raw_os_ostream.h> )
68 #include <llvm/IR/Value.h>
69 #include <llvm/Support/raw_os_ostream.h>
70 #include "clang/Driver/Job.h"
71 #include "llvm/IR/Function.h"
72 #include "llvm/IR/Module.h"
73 #include "llvm/Option/ArgList.h"
74 #else
75 #undefine ENABLE_TOSTRING_LLVM
76 #endif
77 #endif
78 
79 #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
80 #define PRINT(EXPR) \
81  std::cout << "[" << __FILENAME__ << ":" << __func__ << "#" << __LINE__ \
82  << "]: " #EXPR "=" << ::toString(EXPR) << std::endl;
83 
84 template <typename T>
85 std::string typeName(const T* v) {
86  std::stringstream stream;
87  int status;
88 #ifdef _WIN32
89  stream << std::string(typeid(T).name());
90 #else
91  char* demangled = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
92  stream << std::string(demangled);
93  free(demangled);
94 #endif
95  return stream.str();
96 }
97 
98 namespace {
99 
100 template <typename T, typename = void>
101 struct has_toString : std::false_type {};
102 template <typename T>
103 struct has_toString<T, decltype(std::declval<T>().toString(), void())> : std::true_type {
104 };
105 template <class T>
106 inline constexpr bool has_toString_v = has_toString<T>::value;
107 
108 template <typename T, typename = void>
109 struct get_has_toString : std::false_type {};
110 template <typename T>
111 struct get_has_toString<T, decltype(std::declval<T>().get()->toString(), void())>
112  : std::true_type {};
113 template <class T>
115 
116 #ifdef ENABLE_TOSTRING_to_string
117 template <typename T, typename = void>
118 struct has_to_string : std::false_type {};
119 template <typename T>
120 struct has_to_string<T, decltype(std::declval<T>().to_string(), void())>
121  : std::true_type {};
122 template <class T>
123 inline constexpr bool has_to_string_v = has_to_string<T>::value;
124 #endif
125 
126 #ifdef ENABLE_TOSTRING_str
127 template <typename T, typename = void>
128 struct has_str : std::false_type {};
129 template <typename T>
130 struct has_str<T, decltype(std::declval<T>().str(), void())> : std::true_type {};
131 template <class T>
132 inline constexpr bool has_str_v = has_str<T>::value;
133 #endif
134 
135 template <typename T, typename = void>
136 struct has_printTo : std::false_type {};
137 template <typename T>
138 struct has_printTo<T,
139  decltype(std::declval<T>().printTo(std::declval<std::ostream&>()),
140  void())> : std::true_type {};
141 template <class T>
142 inline constexpr bool has_printTo_v = has_printTo<T>::value;
143 
144 } // namespace
145 
146 template <typename T>
147 std::string toString(const T& v) {
148  if constexpr (std::is_same_v<T, std::string>) {
149  return "\"" + v + "\"";
150 #ifdef ENABLE_TOSTRING_RAPIDJSON
151  } else if constexpr (std::is_same_v<T, rapidjson::Value>) {
152  rapidjson::StringBuffer buffer;
153  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
154  v.Accept(writer);
155  return buffer.GetString();
156 #endif
157 #ifdef ENABLE_TOSTRING_LLVM
158  } else if constexpr (std::is_same_v<T, llvm::Module>) {
159  std::string type_str;
160  llvm::raw_string_ostream rso(type_str);
161  v.print(rso, nullptr);
162  return "(" + rso.str() + ")";
163  } else if constexpr (std::is_same_v<T, llvm::Function>) {
164  std::string type_str;
165  llvm::raw_string_ostream rso(type_str);
166  v.print(rso, nullptr);
167  return "(" + rso.str() + ")";
168  } else if constexpr (std::is_same_v<T, llvm::Value>) {
169  std::string type_str;
170  llvm::raw_string_ostream rso(type_str);
171  v.print(rso);
172  return "(" + rso.str() + ")";
173  } else if constexpr (std::is_same_v<T, llvm::Type>) {
174  std::string type_str;
175  llvm::raw_string_ostream rso(type_str);
176  v.print(rso);
177  return "(" + rso.str() + ")";
178  } else if constexpr (std::is_same_v<T, llvm::Triple>) {
179  return v.str();
180  } else if constexpr (std::is_same_v<T, llvm::opt::ArgStringList>) {
181  std::string r;
182  for (unsigned i = 0; i < v.size(); i++) {
183  if (i) {
184  r += ", ";
185  }
186  r += v[i];
187  }
188  return "[" + r + "]";
189  } else if constexpr (std::is_same_v<T, llvm::opt::DerivedArgList>) {
190  std::string r;
191  for (unsigned i = 0; i < v.getNumInputArgStrings(); i++) {
192  if (i) {
193  r += ", ";
194  }
195  r += v.getArgString(i);
196  }
197  return "[" + r + "]";
198  } else if constexpr (std::is_same_v<T, clang::driver::JobList>) {
199  std::string type_str;
200  llvm::raw_string_ostream rso(type_str);
201  v.Print(rso, nullptr, true);
202  return rso.str();
203 #endif
204  } else if constexpr (std::is_same_v<T, bool>) {
205  return v ? "True" : "False";
206  } else if constexpr (std::is_arithmetic_v<T>) {
207  return std::to_string(v);
208 #ifdef ENABLE_TOSTRING_str
209  } else if constexpr (has_str_v<T>) {
210  return v.str();
211 #endif
212 #ifdef ENABLE_TOSTRING_to_string
213  } else if constexpr (has_to_string_v<T>) {
214  return v.to_string();
215 #endif
216  } else if constexpr (has_toString_v<T>) {
217  return v.toString();
218  } else if constexpr (get_has_toString_v<T>) {
219  auto ptr = v.get();
220  return (ptr == NULL ? "NULL" : "&" + ptr->toString());
221  } else if constexpr (std::is_same_v<T, void*>) {
222  std::ostringstream ss;
223  ss << std::hex << (uintptr_t)v;
224  return "0x" + ss.str();
225  } else if constexpr (std::is_same_v<
226  T,
227  std::chrono::time_point<std::chrono::system_clock>>) {
228  std::string s(30, '\0');
229  auto converted_v = (std::chrono::time_point<std::chrono::system_clock>)v;
230  std::time_t ts = std::chrono::system_clock::to_time_t(v);
231  std::strftime(&s[0], s.size(), "%Y-%m-%d %H:%M:%S", std::localtime(&ts));
232  return s + "." +
233  std::to_string((converted_v.time_since_epoch().count() / 1000) % 1000000);
234  } else if constexpr (std::is_same_v<T, JoinType>) {
235  switch (v) {
236  case JoinType::INNER:
237  return "INNER";
238  case JoinType::LEFT:
239  return "LEFT";
240  case JoinType::SEMI:
241  return "SEMI";
242  case JoinType::ANTI:
243  return "ANTI";
244  case JoinType::INVALID:
245  return "INVALID";
246  }
247  UNREACHABLE();
248  return "";
249  } else if constexpr (std::is_pointer_v<T>) {
250  return (v == NULL ? "NULL" : "&" + toString(*v));
251  } else if constexpr (has_printTo_v<T>) {
252  std::ostringstream ss;
253  v.printTo(ss);
254  return ss.str();
255  } else {
256  return typeName(&v);
257  }
258 }
259 
260 template <typename T1, typename T2>
261 std::string toString(const std::pair<T1, T2>& v) {
262  return "(" + toString(v.first) + ", " + toString(v.second) + ")";
263 }
264 
265 template <typename T>
266 std::string toString(const std::vector<T>& v) {
267  auto result = std::string("[");
268  for (size_t i = 0; i < v.size(); ++i) {
269  if (i) {
270  result += ", ";
271  }
272  result += toString(v[i]);
273  }
274  result += "]";
275  return result;
276 }
277 
278 template <typename T1, typename T2>
279 std::string toString(const std::unordered_map<T1, T2>& v) {
280  auto result = std::string("{");
281  size_t i = 0;
282  for (const auto& p : v) {
283  if (i) {
284  result += ", ";
285  }
286  result += toString(p);
287  i++;
288  }
289  result += "}";
290  return result;
291 }
292 
293 template <typename T>
294 std::string toString(const std::list<T>& v) {
295  auto result = std::string("[");
296  size_t i = 0;
297  for (const auto& p : v) {
298  if (i) {
299  result += ", ";
300  }
301  result += toString(p);
302  i++;
303  }
304  result += "]";
305  return result;
306 }
307 
308 template <typename T>
309 std::string toString(const std::unordered_set<T>& v) {
310  auto result = std::string("{");
311  size_t i = 0;
312  for (const auto& p : v) {
313  if (i) {
314  result += ", ";
315  }
316  result += toString(p);
317  i++;
318  }
319  result += "}";
320  return result;
321 }
322 
323 template <typename T>
324 std::string toString(const std::set<T>& v) {
325  auto result = std::string("{");
326  size_t i = 0;
327  for (const auto& p : v) {
328  if (i) {
329  result += ", ";
330  }
331  result += toString(p);
332  i++;
333  }
334  result += "}";
335  return result;
336 }
337 
338 template <typename T>
339 std::string toString(const std::tuple<T, T>& v) {
340  T left, right;
341  std::tie(left, right) = v;
342  return std::string("(") + toString(left) + ", " + toString(right) + ")";
343 }
344 
345 #endif // __CUDACC__
std::string toString(const ExtArgumentType &sig_type)
constexpr bool has_toString_v
Definition: toString.h:106
string name
Definition: setup.in.py:72
tuple r
Definition: test_fsi.py:16
#define UNREACHABLE()
Definition: Logger.h:250
std::string to_string(char const *&&v)
struct get_has_toString< T, decltype(std::declval< T >().get() -> void())> constexpr bool get_has_toString_v
Definition: toString.h:114
std::string typeName(const T *v)
Definition: toString.h:85
constexpr bool has_printTo_v
Definition: toString.h:142
Common Enum definitions for SQL processing.