OmniSciDB  6686921089
 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 << std::hex \
82  << ((std::hash<std::thread::id>()(std::this_thread::get_id())) & 0xffff) \
83  << std::dec << " [" << __FILENAME__ << ":" << __func__ << "#" << __LINE__ \
84  << "]: " #EXPR "=" << ::toString(EXPR) << std::endl \
85  << std::flush;
86 
87 template <typename T>
88 std::string typeName(const T* v) {
89  std::stringstream stream;
90  int status;
91 #ifdef _WIN32
92  stream << std::string(typeid(T).name());
93 #else
94  char* demangled = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
95  stream << std::string(demangled);
96  free(demangled);
97 #endif
98  return stream.str();
99 }
100 
101 template <typename T, typename... Args>
102 std::string typeName(T (*v)(Args... args)) {
103  std::stringstream stream;
104  int status;
105 #ifdef _WIN32
106  stream << std::string(typeid(v).name());
107 #else
108  char* demangled = abi::__cxa_demangle(typeid(v).name(), 0, 0, &status);
109  stream << std::string(demangled);
110  free(demangled);
111 #endif
112  stream << "@0x" << std::hex << (uintptr_t)(reinterpret_cast<const void*>(v));
113  return stream.str();
114 }
115 
116 namespace {
117 
118 template <typename T, typename = void>
119 struct has_toString : std::false_type {};
120 template <typename T>
121 struct has_toString<T, decltype(std::declval<T>().toString(), void())> : std::true_type {
122 };
123 template <class T>
124 inline constexpr bool has_toString_v = has_toString<T>::value;
125 
126 template <typename T, typename = void>
127 struct get_has_toString : std::false_type {};
128 template <typename T>
129 struct get_has_toString<T, decltype(std::declval<T>().get()->toString(), void())>
130  : std::true_type {};
131 template <class T>
133 
134 #ifdef ENABLE_TOSTRING_to_string
135 template <typename T, typename = void>
136 struct has_to_string : std::false_type {};
137 template <typename T>
138 struct has_to_string<T, decltype(std::declval<T>().to_string(), void())>
139  : std::true_type {};
140 template <class T>
141 inline constexpr bool has_to_string_v = has_to_string<T>::value;
142 #endif
143 
144 #ifdef ENABLE_TOSTRING_str
145 template <typename T, typename = void>
146 struct has_str : std::false_type {};
147 template <typename T>
148 struct has_str<T, decltype(std::declval<T>().str(), void())> : std::true_type {};
149 template <class T>
150 inline constexpr bool has_str_v = has_str<T>::value;
151 #endif
152 
153 template <typename T, typename = void>
154 struct has_printTo : std::false_type {};
155 template <typename T>
156 struct has_printTo<T,
157  decltype(std::declval<T>().printTo(std::declval<std::ostream&>()),
158  void())> : std::true_type {};
159 template <class T>
160 inline constexpr bool has_printTo_v = has_printTo<T>::value;
161 
162 } // namespace
163 
164 template <typename T>
165 std::string toString(const T& v) {
166  if constexpr (std::is_same_v<T, std::string>) { // NOLINT
167  return "\"" + v + "\"";
168 #ifdef ENABLE_TOSTRING_RAPIDJSON
169  } else if constexpr (std::is_same_v<T, rapidjson::Value>) { // NOLINT
170  rapidjson::StringBuffer buffer;
171  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
172  v.Accept(writer);
173  return buffer.GetString();
174 #endif
175 #ifdef ENABLE_TOSTRING_LLVM
176  } else if constexpr (std::is_same_v<T, llvm::Module>) { // NOLINT
177  std::string type_str;
178  llvm::raw_string_ostream rso(type_str);
179  v.print(rso, nullptr);
180  return "(" + rso.str() + ")";
181  } else if constexpr (std::is_same_v<T, llvm::Function>) { // NOLINT
182  std::string type_str;
183  llvm::raw_string_ostream rso(type_str);
184  v.print(rso, nullptr);
185  return "(" + rso.str() + ")";
186  } else if constexpr (std::is_same_v<T, llvm::Value>) { // NOLINT
187  std::string type_str;
188  llvm::raw_string_ostream rso(type_str);
189  v.print(rso);
190  return "(" + rso.str() + ")";
191  } else if constexpr (std::is_same_v<T, llvm::Argument>) { // NOLINT
192  std::string type_str;
193  llvm::raw_string_ostream rso(type_str);
194  v.print(rso);
195  return "(" + rso.str() + ")";
196  } else if constexpr (std::is_same_v<T, llvm::Type>) { // NOLINT
197  std::string type_str;
198  llvm::raw_string_ostream rso(type_str);
199  v.print(rso);
200  return "(" + rso.str() + ")";
201  } else if constexpr (std::is_same_v<T, llvm::Triple>) { // NOLINT
202  return v.str();
203  } else if constexpr (std::is_same_v<T, llvm::opt::ArgStringList>) { // NOLINT
204  std::string r;
205  for (unsigned i = 0; i < v.size(); i++) {
206  if (i) {
207  r += ", ";
208  }
209  r += v[i];
210  }
211  return "[" + r + "]";
212  } else if constexpr (std::is_same_v<T, llvm::opt::DerivedArgList>) { // NOLINT
213  std::string r;
214  for (unsigned i = 0; i < v.getNumInputArgStrings(); i++) {
215  if (i) {
216  r += ", ";
217  }
218  r += v.getArgString(i);
219  }
220  return "[" + r + "]";
221  } else if constexpr (std::is_same_v<T, clang::driver::JobList>) { // NOLINT
222  std::string type_str;
223  llvm::raw_string_ostream rso(type_str);
224  v.Print(rso, nullptr, true);
225  return rso.str();
226 #endif
227  } else if constexpr (std::is_same_v<T, bool>) { // NOLINT
228  return v ? "True" : "False";
229  } else if constexpr (std::is_arithmetic_v<T>) { // NOLINT
230  return std::to_string(v);
231 #ifdef ENABLE_TOSTRING_str
232  } else if constexpr (has_str_v<T>) { // NOLINT
233  return v.str();
234 #endif
235 #ifdef ENABLE_TOSTRING_to_string
236  } else if constexpr (has_to_string_v<T>) { // NOLINT
237  return v.to_string();
238 #endif
239  } else if constexpr (has_toString_v<T>) { // NOLINT
240  return v.toString();
241  } else if constexpr (get_has_toString_v<T>) {
242  auto ptr = v.get();
243  return (ptr == NULL ? "NULL" : "&" + ptr->toString());
244  } else if constexpr (std::is_same_v<T, void*>) {
245  std::ostringstream ss;
246  ss << std::hex << (uintptr_t)v;
247  return "0x" + ss.str();
248  } else if constexpr (std::is_same_v<
249  T,
250  std::chrono::time_point<std::chrono::system_clock>>) {
251  std::string s(30, '\0');
252  auto converted_v = (std::chrono::time_point<std::chrono::system_clock>)v;
253  std::time_t ts = std::chrono::system_clock::to_time_t(v);
254  std::strftime(&s[0], s.size(), "%Y-%m-%d %H:%M:%S", std::localtime(&ts));
255  return s + "." +
256  std::to_string((converted_v.time_since_epoch().count() / 1000) % 1000000);
257  } else if constexpr (std::is_same_v<T, JoinType>) {
258  switch (v) {
259  case JoinType::INNER:
260  return "INNER";
261  case JoinType::LEFT:
262  return "LEFT";
263  case JoinType::SEMI:
264  return "SEMI";
265  case JoinType::ANTI:
266  return "ANTI";
267  case JoinType::INVALID:
268  return "INVALID";
269  }
270  UNREACHABLE();
271  return "";
272  } else if constexpr (std::is_pointer_v<T>) {
273  return (v == NULL ? "NULL" : "&" + toString(*v));
274  } else if constexpr (has_printTo_v<T>) {
275  std::ostringstream ss;
276  v.printTo(ss);
277  return ss.str();
278  } else {
279  return typeName(&v);
280  }
281 }
282 
283 template <typename T1, typename T2>
284 std::string toString(const std::pair<T1, T2>& v) {
285  return "(" + toString(v.first) + ", " + toString(v.second) + ")";
286 }
287 
288 template <typename T>
289 std::string toString(const std::vector<T>& v) {
290  auto result = std::string("[");
291  for (size_t i = 0; i < v.size(); ++i) {
292  if (i) {
293  result += ", ";
294  }
295  result += toString(v[i]);
296  }
297  result += "]";
298  return result;
299 }
300 
301 template <typename T1, typename T2>
302 std::string toString(const std::unordered_map<T1, T2>& v) {
303  auto result = std::string("{");
304  size_t i = 0;
305  for (const auto& p : v) {
306  if (i) {
307  result += ", ";
308  }
309  result += toString(p);
310  i++;
311  }
312  result += "}";
313  return result;
314 }
315 
316 template <typename T>
317 std::string toString(const std::list<T>& v) {
318  auto result = std::string("[");
319  size_t i = 0;
320  for (const auto& p : v) {
321  if (i) {
322  result += ", ";
323  }
324  result += toString(p);
325  i++;
326  }
327  result += "]";
328  return result;
329 }
330 
331 template <typename T>
332 std::string toString(const std::unordered_set<T>& v) {
333  auto result = std::string("{");
334  size_t i = 0;
335  for (const auto& p : v) {
336  if (i) {
337  result += ", ";
338  }
339  result += toString(p);
340  i++;
341  }
342  result += "}";
343  return result;
344 }
345 
346 template <typename T>
347 std::string toString(const std::set<T>& v) {
348  auto result = std::string("{");
349  size_t i = 0;
350  for (const auto& p : v) {
351  if (i) {
352  result += ", ";
353  }
354  result += toString(p);
355  i++;
356  }
357  result += "}";
358  return result;
359 }
360 
361 template <typename T>
362 std::string toString(const std::tuple<T, T>& v) {
363  T left, right;
364  std::tie(left, right) = v;
365  return std::string("(") + toString(left) + ", " + toString(right) + ")";
366 }
367 
368 #endif // __CUDACC__
std::string toString(const ExtArgumentType &sig_type)
constexpr bool has_toString_v
Definition: toString.h:124
string name
Definition: setup.in.py:72
#define UNREACHABLE()
Definition: Logger.h:253
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:132
std::string typeName(const T *v)
Definition: toString.h:88
constexpr bool has_printTo_v
Definition: toString.h:160
Common Enum definitions for SQL processing.