24#ifndef CRITERION_INTERNAL_ASSERT_TOSTR_H_
25#define CRITERION_INTERNAL_ASSERT_TOSTR_H_
31# include <type_traits>
34extern "C" char *cr_user_str_tostr(
const char **);
35extern "C" char *cr_user_wcs_tostr(
const wchar_t **);
37namespace criterion {
namespace internal {
namespace stream_override {
40struct make_void {
typedef void type; };
43using __void_t =
typename make_void<T...>::type;
45template<
typename T,
typename =
void>
46struct __is_printable: std::false_type {};
49struct __is_printable<T,
50 __void_t<decltype(
std::
declval<std::ostream&>() << std::declval<T>())>>
53template<
typename T,
typename =
void>
54struct __is_iterable: std::false_type {};
57struct __is_iterable<T,
76 typename =
typename std::enable_if<!__is_iterable<T>::value || __is_printable<T>::value>::type,
typename =
void>
83template <
typename T,
typename U>
95 const char *cstr = str.c_str();
96 char *fmt = cr_user_str_tostr(&cstr);
104 const wchar_t *cstr = str.c_str();
105 char *fmt = cr_user_wcs_tostr(&cstr);
121 return ::criterion::internal::stream_override::operator<<(
s,
nullptr);
123 auto flags =
s.base.flags();
124 s.base <<
"@" << std::hex << (uintptr_t)ptr;
134 s.base << signed (i);
140 s.base << unsigned (i);
154 typename =
typename std::enable_if<__is_iterable<T>::value && !__is_printable<T>::value>::type>
159 for (
auto &e : container) {
160 s << std::endl <<
"\t" << e <<
", ";
175# define CRI_VALUE_ESCAPE(T, X) cri_val_escape<std::remove_reference<T>::type>(X)
179namespace criterion {
namespace internal {
182struct is_trivial : std::integral_constant<bool,
183 std::is_fundamental<T>::value || std::is_pointer<T>::value> {};
188 typename =
typename std::enable_if<!std::is_pointer<T>::value>::type>
189constexpr T&& cri_val_escape(T&& v)
191 return std::forward<T>(v);
195 typename =
typename std::enable_if<!std::is_pointer<T>::value>::type>
196constexpr T& cri_val_escape(T& v)
203 typename =
typename std::enable_if<std::is_pointer<T>::value>::type>
204constexpr T cri_val_escape(T v)
213 typename =
typename std::enable_if<std::is_same<Char, char>::value>::type>
214std::string cri_val_escape(Char
const *
const &
s)
216 return std::string(
s);
220 typename =
typename std::enable_if<std::is_same<Char, wchar_t>::value>::type>
221std::wstring cri_val_escape(Char
const *
const &
s)
223 return std::wstring(
s);
227std::string cri_val_escape(
const char (&
s)[N])
229 return std::string(
s);
233std::wstring cri_val_escape(
const wchar_t (&
s)[N])
235 return std::wstring(
s);
238# define CRI_USER_TOSTR(Tag, Var) \
240 std::stringstream sstr; \
241 criterion::internal::stream_override::ostream cri_os { sstr };\
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'; \
250# define CRI_ASSERT_UNPRINTABLE(Var) CRI_USER_TOSTR(, Var)
251# define CRI_ASSERT_NAMESPACES \
252 using namespace criterion::internal::operators
254# define CRI_USER_TOSTR_ARR(Str, Arr, Tag) \
256 std::stringstream cri_sstr; \
257 cri_sstr << "(" CR_STR(CRI_ASSERT_TYPE_TAG(Tag)) "[" \
258 << CRI_ASSERT_TYPE_TAG_ARRLEN(Tag) \
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); \
267 cri_sstr << "\t[" << cri_i << "] = " << cri_line; \
269 while ((cri_line = cri_strtok_r(NULL, "\n", &cri_saveptr))) { \
270 cri_sstr << "\n\t" << cri_line; \
274 cr_asprintf_free(cri_repr); \
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'; \
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)
291# define CRI_USER_TOSTR_ARR(Str, Arr, Tag) \
293 size_t cri_off = 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)); \
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); \
305 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, \
306 "\t[%" CRI_PRIuSIZE "] = %s", cri_i, cri_line); \
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); \
311 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, ",\n"); \
313 cr_asprintf_free(cri_repr); \
315 cri_fmt_bprintf(&(Str), &cri_off, &cri_sz, "}"); \
CURL_EXTERN CURLMcode curl_socket_t s
decltype(nullptr) nullptr_t
basic_ostream< char, traits > & operator<<(basic_ostream< char, traits > &, const char *)
basic_ostream< char, char_traits< char > > ostream