OmniSciDB  8fa3bf436f
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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 
55 #ifdef ENABLE_TOSTRING_RAPIDJSON
56 #if __has_include(<rapidjson/document.h> )
57 #include <rapidjson/document.h>
58 #include <rapidjson/stringbuffer.h>
59 #include <rapidjson/writer.h>
60 #else
61 #undefine ENABLE_TOSTRING_RAPIDJSON
62 #endif
63 #endif
64 
65 #ifdef ENABLE_TOSTRING_LLVM
66 #if __has_include(<llvm/Support/raw_os_ostream.h> )
67 #include <llvm/IR/Value.h>
68 #include <llvm/Support/raw_os_ostream.h>
69 #include "llvm/IR/Function.h"
70 #include "llvm/IR/Module.h"
71 #else
72 #undefine ENABLE_TOSTRING_LLVM
73 #endif
74 #endif
75 
76 #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
77 #define PRINT(EXPR) \
78  std::cout << "[" << __FILENAME__ << ":" << __func__ << "#" << __LINE__ \
79  << "]: " #EXPR "=" << ::toString(EXPR) << std::endl;
80 
81 template <typename T>
82 std::string typeName(const T* v) {
83  std::stringstream stream;
84  int status;
85 #ifdef _WIN32
86  stream << std::string(typeid(T).name());
87 #else
88  char* demangled = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
89  stream << std::string(demangled);
90  free(demangled);
91 #endif
92  return stream.str();
93 }
94 
95 namespace {
96 
97 template <typename T, typename = void>
98 struct has_toString : std::false_type {};
99 template <typename T>
100 struct has_toString<T, decltype(std::declval<T>().toString(), void())> : std::true_type {
101 };
102 template <class T>
103 inline constexpr bool has_toString_v = has_toString<T>::value;
104 
105 template <typename T, typename = void>
106 struct get_has_toString : std::false_type {};
107 template <typename T>
108 struct get_has_toString<T, decltype(std::declval<T>().get()->toString(), void())>
109  : std::true_type {};
110 template <class T>
112 
113 #ifdef ENABLE_TOSTRING_to_string
114 template <typename T, typename = void>
115 struct has_to_string : std::false_type {};
116 template <typename T>
117 struct has_to_string<T, decltype(std::declval<T>().to_string(), void())>
118  : std::true_type {};
119 template <class T>
120 inline constexpr bool has_to_string_v = has_to_string<T>::value;
121 #endif
122 
123 #ifdef ENABLE_TOSTRING_str
124 template <typename T, typename = void>
125 struct has_str : std::false_type {};
126 template <typename T>
127 struct has_str<T, decltype(std::declval<T>().str(), void())> : std::true_type {};
128 template <class T>
129 inline constexpr bool has_str_v = has_str<T>::value;
130 #endif
131 
132 } // namespace
133 
134 template <typename T>
135 std::string toString(const T& v) {
136  if constexpr (std::is_same_v<T, std::string>) {
137  return "\"" + v + "\"";
138 #ifdef ENABLE_TOSTRING_RAPIDJSON
139  } else if constexpr (std::is_same_v<T, rapidjson::Value>) {
140  rapidjson::StringBuffer buffer;
141  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
142  v.Accept(writer);
143  return buffer.GetString();
144 #endif
145 #ifdef ENABLE_TOSTRING_LLVM
146  } else if constexpr (std::is_same_v<T, llvm::Module>) {
147  std::string type_str;
148  llvm::raw_string_ostream rso(type_str);
149  v.print(rso, nullptr);
150  return "(" + rso.str() + ")";
151  } else if constexpr (std::is_same_v<T, llvm::Function>) {
152  std::string type_str;
153  llvm::raw_string_ostream rso(type_str);
154  v.print(rso, nullptr);
155  return "(" + rso.str() + ")";
156  } else if constexpr (std::is_same_v<T, llvm::Value>) {
157  std::string type_str;
158  llvm::raw_string_ostream rso(type_str);
159  v.print(rso);
160  return "(" + rso.str() + ")";
161  } else if constexpr (std::is_same_v<T, llvm::Type>) {
162  std::string type_str;
163  llvm::raw_string_ostream rso(type_str);
164  v.print(rso);
165  return "(" + rso.str() + ")";
166  } else if constexpr (std::is_same_v<T, llvm::Triple>) {
167  return v.str();
168 #endif
169  } else if constexpr (std::is_same_v<T, bool>) {
170  return v ? "True" : "False";
171  } else if constexpr (std::is_arithmetic_v<T>) {
172  return std::to_string(v);
173 #ifdef ENABLE_TOSTRING_str
174  } else if constexpr (has_str_v<T>) {
175  return v.str();
176 #endif
177 #ifdef ENABLE_TOSTRING_to_string
178  } else if constexpr (has_to_string_v<T>) {
179  return v.to_string();
180 #endif
181  } else if constexpr (has_toString_v<T>) {
182  return v.toString();
183  } else if constexpr (get_has_toString_v<T>) {
184  auto ptr = v.get();
185  return (ptr == NULL ? "NULL" : "&" + ptr->toString());
186  } else if constexpr (std::is_same_v<T, void*>) {
187  std::ostringstream ss;
188  ss << std::hex << (uintptr_t)v;
189  return "0x" + ss.str();
190  } else if constexpr (std::is_same_v<
191  T,
192  std::chrono::time_point<std::chrono::system_clock>>) {
193  std::string s(30, '\0');
194  auto converted_v = (std::chrono::time_point<std::chrono::system_clock>)v;
195  std::time_t ts = std::chrono::system_clock::to_time_t(v);
196  std::strftime(&s[0], s.size(), "%Y-%m-%d %H:%M:%S", std::localtime(&ts));
197  return s + "." +
198  std::to_string((converted_v.time_since_epoch().count() / 1000) % 1000000);
199  } else if constexpr (std::is_pointer_v<T>) {
200  return (v == NULL ? "NULL" : "&" + toString(*v));
201  } else {
202  return typeName(&v);
203  }
204 }
205 
206 template <typename T1, typename T2>
207 std::string toString(const std::pair<T1, T2>& v) {
208  return "(" + toString(v.first) + ", " + toString(v.second) + ")";
209 }
210 
211 template <typename T>
212 std::string toString(const std::vector<T>& v) {
213  auto result = std::string("[");
214  for (size_t i = 0; i < v.size(); ++i) {
215  if (i) {
216  result += ", ";
217  }
218  result += toString(v[i]);
219  }
220  result += "]";
221  return result;
222 }
223 
224 template <typename T1, typename T2>
225 std::string toString(const std::unordered_map<T1, T2>& v) {
226  auto result = std::string("{");
227  size_t i = 0;
228  for (const auto& p : v) {
229  if (i) {
230  result += ", ";
231  }
232  result += toString(p);
233  i++;
234  }
235  result += "}";
236  return result;
237 }
238 
239 template <typename T>
240 std::string toString(const std::list<T>& v) {
241  auto result = std::string("[");
242  size_t i = 0;
243  for (const auto& p : v) {
244  if (i) {
245  result += ", ";
246  }
247  result += toString(p);
248  i++;
249  }
250  result += "]";
251  return result;
252 }
253 
254 template <typename T>
255 std::string toString(const std::unordered_set<T>& v) {
256  auto result = std::string("{");
257  size_t i = 0;
258  for (const auto& p : v) {
259  if (i) {
260  result += ", ";
261  }
262  result += toString(p);
263  i++;
264  }
265  result += "}";
266  return result;
267 }
268 
269 template <typename T>
270 std::string toString(const std::set<T>& v) {
271  auto result = std::string("{");
272  size_t i = 0;
273  for (const auto& p : v) {
274  if (i) {
275  result += ", ";
276  }
277  result += toString(p);
278  i++;
279  }
280  result += "}";
281  return result;
282 }
283 
284 template <typename T>
285 std::string toString(const std::tuple<T, T>& v) {
286  T left, right;
287  std::tie(left, right) = v;
288  return std::string("(") + toString(left) + ", " + toString(right) + ")";
289 }
290 
291 #endif // __CUDACC__
std::string toString(const ExtArgumentType &sig_type)
constexpr bool has_toString_v
Definition: toString.h:103
string name
Definition: setup.in.py:72
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:111
std::string typeName(const T *v)
Definition: toString.h:82