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