Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
tostr.h
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright © 2017 Franklin "Snaipe" Mathieu <http://snai.pe/>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#ifndef CRITERION_INTERNAL_ASSERT_TOSTR_H_
25#define CRITERION_INTERNAL_ASSERT_TOSTR_H_
26
27#include "tag.h"
28
29#ifdef __cplusplus
30
31# include <type_traits>
32# include <utility>
33
34extern "C" char *cr_user_str_tostr(const char **);
35extern "C" char *cr_user_wcs_tostr(const wchar_t **);
36
37namespace criterion { namespace internal { namespace stream_override {
38
39template< class... T>
40struct make_void { typedef void type; };
41
42template< class... T>
43using __void_t = typename make_void<T...>::type;
44
45template<typename T, typename = void>
46struct __is_printable: std::false_type {};
47
48template<typename T>
49struct __is_printable<T,
50 __void_t<decltype(std::declval<std::ostream&>() << std::declval<T>())>>
51: std::true_type {};
52
53template<typename T, typename = void>
54struct __is_iterable: std::false_type {};
55
56template<typename T>
57struct __is_iterable<T,
58 __void_t<decltype(std::declval<T>().begin())>>
59: std::true_type {};
60
61struct ostream {
62 constexpr ostream(std::ostream &s)
63 : base(s)
64 {}
65
66 std::ostream &base;
67};
68
69inline ostream& operator<<(ostream& s, std::ostream& (*func)(std::ostream&))
70{
71 s.base << func;
72 return s;
73}
74
75template <typename T,
76 typename = typename std::enable_if<!__is_iterable<T>::value || __is_printable<T>::value>::type, typename = void>
77inline ostream &operator<<(ostream &s, const T &value)
78{
79 s.base << value;
80 return s;
81}
82
83template <typename T, typename U>
84inline ostream &operator<<(ostream &s, const std::pair<T, U> &value)
85{
86 s.base << "[";
87 s << value.first;
88 s.base << "]: ";
89 s << value.second;
90 return s;
91}
92
93inline ostream &operator<<(ostream &s, const std::string &str)
94{
95 const char *cstr = str.c_str();
96 char *fmt = cr_user_str_tostr(&cstr);
97 s.base << fmt;
98 free(fmt);
99 return s;
100}
101
102inline ostream &operator<<(ostream &s, const std::wstring &str)
103{
104 const wchar_t *cstr = str.c_str();
105 char *fmt = cr_user_wcs_tostr(&cstr);
106 s.base << fmt;
107 free(fmt);
108 return s;
109}
110
111inline ostream &operator<<(ostream &s, const std::nullptr_t &ptr)
112{
113 (void) ptr;
114 s.base << "nullptr";
115 return s;
116}
117
118inline ostream &operator<<(ostream &s, void *const &ptr)
119{
120 if (!ptr)
121 return ::criterion::internal::stream_override::operator<<(s, nullptr);
122
123 auto flags = s.base.flags();
124 s.base << "@" << std::hex << (uintptr_t)ptr;
125 s.base.flags(flags);
126 return s;
127}
128
129/* These overloads are necessary as int8_t and uint8_t are outputted as
130 characters by default. why. */
131
132inline ostream &operator<<(ostream &s, const int8_t &i)
133{
134 s.base << signed (i);
135 return s;
136}
137
138inline ostream &operator<<(ostream &s, const uint8_t &i)
139{
140 s.base << unsigned (i);
141 return s;
142}
143
144inline ostream &operator<<(ostream &s, const char &c)
145{
146 s.base << c;
147 return s;
148}
149
150/* These overloads are there because none of the stl containers implement <<.
151 We provide a sensible string representation for iterable types. */
152
153template <typename T,
154 typename = typename std::enable_if<__is_iterable<T>::value && !__is_printable<T>::value>::type>
155inline ostream &operator<<(ostream &s, const T &container)
156{
157 s.base << "{";
158 size_t count = 0;
159 for (auto &e : container) {
160 s << std::endl << "\t" << e << ", ";
161 count++;
162 }
163 if (count > 0) {
164 s.base << std::endl;
165 }
166 s.base << "}";
167 return s;
168}
169
170}}} /* criterion::internal::stream_override */
171
172/* The value escape is only necessary for C++ where some type conversion
173 is needed between literals and more complex types of incompatible types. */
174
175# define CRI_VALUE_ESCAPE(T, X) cri_val_escape<std::remove_reference<T>::type>(X)
176
177/* Generic implementation of cri_val_escape */
178
179namespace criterion { namespace internal {
180
181template <class T>
182struct is_trivial : std::integral_constant<bool,
183 std::is_fundamental<T>::value || std::is_pointer<T>::value> {};
184
185}} /* criterion::internal */
186
187template <typename T,
188 typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
189constexpr T&& cri_val_escape(T&& v)
190{
191 return std::forward<T>(v);
192}
193
194template <typename T,
195 typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
196constexpr T& cri_val_escape(T& v)
197{
198 return v;
199}
200
201/* force an array decay */
202template <typename T,
203 typename = typename std::enable_if<std::is_pointer<T>::value>::type>
204constexpr T cri_val_escape(T v)
205{
206 return v;
207}
208
209/* We need these specializations to convert seemingly between string literals
210 and STL string types */
211
212template <class Char,
213 typename = typename std::enable_if<std::is_same<Char, char>::value>::type>
214std::string cri_val_escape(Char const *const &s)
215{
216 return std::string(s);
217}
218
219template <class Char,
220 typename = typename std::enable_if<std::is_same<Char, wchar_t>::value>::type>
221std::wstring cri_val_escape(Char const *const &s)
222{
223 return std::wstring(s);
224}
225
226template <size_t N>
227std::string cri_val_escape(const char (&s)[N])
228{
229 return std::string(s);
230}
231
232template <size_t N>
233std::wstring cri_val_escape(const wchar_t (&s)[N])
234{
235 return std::wstring(s);
236}
237
238# define CRI_USER_TOSTR(Tag, Var) \
239 ([&]() -> char * { \
240 std::stringstream sstr; \
241 criterion::internal::stream_override::ostream cri_os { sstr };\
242 cri_os << (Var); \
243 \
244 const std::string str = sstr.str(); \
245 char *out = static_cast<char *>(std::malloc(str.size() + 1)); \
246 std::copy(str.begin(), str.end(), out); \
247 out[str.size()] = '\0'; \
248 return out; \
249 } ())
250# define CRI_ASSERT_UNPRINTABLE(Var) CRI_USER_TOSTR(, Var)
251# define CRI_ASSERT_NAMESPACES \
252 using namespace criterion::internal::operators
253
254# define CRI_USER_TOSTR_ARR(Str, Arr, Tag) \
255 do { \
256 std::stringstream cri_sstr; \
257 cri_sstr << "(" CR_STR(CRI_ASSERT_TYPE_TAG(Tag)) "[" \
258 << CRI_ASSERT_TYPE_TAG_ARRLEN(Tag) \
259 << "]) {\n"; \
260 \
261 for (size_t cri_i = 0; cri_i < cri_size; ++cri_i) { \
262 char *cri_repr = CRI_USER_TOSTR(Tag, (Arr)[cri_i]); \
263 char *cri_saveptr = NULL; \
264 char *cri_line = cri_strtok_r(cri_repr, "\n", &cri_saveptr); \
265 \
266 if (cri_line) { \
267 cri_sstr << "\t[" << cri_i << "] = " << cri_line; \
268 \
269 while ((cri_line = cri_strtok_r(NULL, "\n", &cri_saveptr))) { \
270 cri_sstr << "\n\t" << cri_line; \
271 } \
272 cri_sstr << ",\n"; \
273 } \
274 cr_asprintf_free(cri_repr); \
275 } \
276 cri_sstr << "}"; \
277 \
278 const std::string cri_ccstr = cri_sstr.str(); \
279 Str = static_cast<char *>(std::malloc(cri_ccstr.size() + 1)); \
280 std::copy(cri_ccstr.begin(), cri_ccstr.end(), Str); \
281 Str[cri_ccstr.size()] = '\0'; \
282 } while (0)
283
284#else /* !__cplusplus */
285
286# define CRI_VALUE_ESCAPE(T, X) X
287# define CRI_USER_TOSTR(Tag, Var) CRI_USER_TAG_ID(tostr, Tag)(&(Var))
288# define CRI_ASSERT_UNPRINTABLE(Var) "<unprintable>"
289# define CRI_ASSERT_NAMESPACES do {} while (0)
290
291# define CRI_USER_TOSTR_ARR(Str, Arr, Tag) \
292 do { \
293 size_t cri_off = 0; \
294 size_t cri_sz = 0; \
295 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, "(" \
296 CR_STR(CRI_ASSERT_TYPE_TAG(Tag)) "[%" CRI_PRIuSIZE "]) {\n", \
297 CRI_ASSERT_TYPE_TAG_ARRLEN(Tag)); \
298 \
299 for (size_t cri_i = 0; cri_i < cri_size; ++cri_i) { \
300 char *cri_repr = CRI_USER_TAG_ID(tostr, Tag)(&(Arr)[cri_i]); \
301 char *cri_saveptr = NULL; \
302 char *cri_line = cri_strtok_r(cri_repr, "\n", &cri_saveptr); \
303 \
304 if (cri_line) { \
305 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, \
306 "\t[%" CRI_PRIuSIZE "] = %s", cri_i, cri_line); \
307 \
308 while ((cri_line = cri_strtok_r(NULL, "\n", &cri_saveptr))) { \
309 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, "\n\t%s", cri_line); \
310 } \
311 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, ",\n"); \
312 } \
313 cr_asprintf_free(cri_repr); \
314 } \
315 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, "}"); \
316 } while (0)
317
318#endif /* !__cplusplus */
319
320#endif /* !CRITERION_INTERNAL_ASSERT_TOSTR_H_ */
#define free
Definition civetweb.c:1542
int value
Definition lsqlite3.c:2155
CURL_EXTERN CURLMcode curl_socket_t s
Definition multi.h:318
Definition doctest.h:522
decltype(nullptr) nullptr_t
Definition doctest.h:523
basic_ostream< char, traits > & operator<<(basic_ostream< char, traits > &, const char *)
basic_ostream< char, char_traits< char > > ostream
Definition doctest.h:531