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