OmniSciDB  a7179b2938
 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 <iostream>
44 #include <sstream>
45 #include <type_traits>
46 #include <unordered_map>
47 #include <unordered_set>
48 #include <vector>
49 
50 #ifdef ENABLE_TOSTRING_RAPIDJSON
51 #if __has_include(<rapidjson/document.h> )
52 #include <rapidjson/document.h>
53 #include <rapidjson/stringbuffer.h>
54 #include <rapidjson/writer.h>
55 #else
56 #undefine ENABLE_TOSTRING_RAPIDJSON
57 #endif
58 #endif
59 
60 #ifdef ENABLE_TOSTRING_LLVM
61 #if __has_include(<llvm/Support/raw_os_ostream.h> )
62 #include <llvm/IR/Value.h>
63 #include <llvm/Support/raw_os_ostream.h>
64 #include "llvm/IR/Function.h"
65 #include "llvm/IR/Module.h"
66 #else
67 #undefine ENABLE_TOSTRING_LLVM
68 #endif
69 #endif
70 
71 #define PRINT(EXPR) \
72  std::cout << __func__ << "#" << __LINE__ << ": " #EXPR "=" << ::toString(EXPR) \
73  << std::endl;
74 
75 template <typename T>
76 std::string typeName(const T* v) {
77  std::stringstream stream;
78  int status;
79  char* demangled = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
80  stream << std::string(demangled);
81  free(demangled);
82  return stream.str();
83 }
84 
85 namespace {
86 
87 template <typename T, typename = void>
88 struct has_toString : std::false_type {};
89 template <typename T>
90 struct has_toString<T, decltype(std::declval<T>().toString(), void())> : std::true_type {
91 };
92 template <class T>
93 inline constexpr bool has_toString_v = has_toString<T>::value;
94 
95 template <typename T, typename = void>
96 struct get_has_toString : std::false_type {};
97 template <typename T>
98 struct get_has_toString<T, decltype(std::declval<T>().get()->toString(), void())>
99  : std::true_type {};
100 template <class T>
101 inline constexpr bool get_has_toString_v = get_has_toString<T>::value;
102 
103 #ifdef ENABLE_TOSTRING_to_string
104 template <typename T, typename = void>
105 struct has_to_string : std::false_type {};
106 template <typename T>
107 struct has_to_string<T, decltype(std::declval<T>().to_string(), void())>
108  : std::true_type {};
109 template <class T>
110 inline constexpr bool has_to_string_v = has_to_string<T>::value;
111 #endif
112 
113 #ifdef ENABLE_TOSTRING_str
114 template <typename T, typename = void>
115 struct has_str : std::false_type {};
116 template <typename T>
117 struct has_str<T, decltype(std::declval<T>().str(), void())> : std::true_type {};
118 template <class T>
119 inline constexpr bool has_str_v = has_str<T>::value;
120 #endif
121 
122 } // namespace
123 
124 template <typename T>
125 std::string toString(const T& v) {
126  if constexpr (std::is_same_v<T, std::string>) {
127  return "\"" + v + "\"";
128 #ifdef ENABLE_TOSTRING_RAPIDJSON
129  } else if constexpr (std::is_same_v<T, rapidjson::Value>) {
130  rapidjson::StringBuffer buffer;
131  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
132  v.Accept(writer);
133  return buffer.GetString();
134 #endif
135 #ifdef ENABLE_TOSTRING_LLVM
136  } else if constexpr (std::is_same_v<T, llvm::Module>) {
137  std::string type_str;
138  llvm::raw_string_ostream rso(type_str);
139  v.print(rso, nullptr);
140  return "(" + rso.str() + ")";
141  } else if constexpr (std::is_same_v<T, llvm::Function>) {
142  std::string type_str;
143  llvm::raw_string_ostream rso(type_str);
144  v.print(rso, nullptr);
145  return "(" + rso.str() + ")";
146  } else if constexpr (std::is_same_v<T, llvm::Value>) {
147  std::string type_str;
148  llvm::raw_string_ostream rso(type_str);
149  v.print(rso);
150  return "(" + rso.str() + ")";
151 #endif
152  } else if constexpr (std::is_same_v<T, bool>) {
153  return v ? "True" : "False";
154  } else if constexpr (std::is_arithmetic_v<T>) {
155  return std::to_string(v);
156 #ifdef ENABLE_TOSTRING_str
157  } else if constexpr (has_str_v<T>) {
158  return v.str();
159 #endif
160 #ifdef ENABLE_TOSTRING_to_string
161  } else if constexpr (has_to_string_v<T>) {
162  return v.to_string();
163 #endif
164  } else if constexpr (has_toString_v<T>) {
165  return v.toString();
166  } else if constexpr (get_has_toString_v<T>) {
167  return v.get()->toString();
168  } else if constexpr (std::is_same_v<T, void*>) {
169  std::ostringstream ss;
170  ss << std::hex << (uintptr_t)v;
171  return "0x" + ss.str();
172  } else if constexpr (std::is_pointer_v<T>) {
173  return (v == NULL ? "NULL" : "&" + toString(*v));
174  } else {
175  return typeName(&v);
176  }
177 }
178 
179 template <typename T1, typename T2>
180 std::string toString(const std::pair<T1, T2>& v) {
181  return "(" + toString(v.first) + ", " + toString(v.second) + ")";
182 }
183 
184 template <typename T>
185 std::string toString(const std::vector<T>& v) {
186  auto result = std::string("[");
187  for (size_t i = 0; i < v.size(); ++i) {
188  if (i) {
189  result += ", ";
190  }
191  result += toString(v[i]);
192  }
193  result += "]";
194  return result;
195 }
196 
197 template <typename T1, typename T2>
198 std::string toString(const std::unordered_map<T1, T2>& v) {
199  auto result = std::string("{");
200  size_t i = 0;
201  for (const auto& p : v) {
202  if (i) {
203  result += ", ";
204  }
205  result += toString(p);
206  i++;
207  }
208  result += "}";
209  return result;
210 }
211 
212 template <typename T>
213 std::string toString(const std::unordered_set<T>& v) {
214  auto result = std::string("{");
215  size_t i = 0;
216  for (const auto& p : v) {
217  if (i) {
218  result += ", ";
219  }
220  result += toString(p);
221  i++;
222  }
223  result += "}";
224  return result;
225 }
226 
227 #endif // __cplusplus >= 201703L
228 #endif // __CUDACC__
std::string toString(const ExtArgumentType &sig_type)
std::string to_string(char const *&&v)
string name
Definition: setup.py:35