Commit 9a39a499 authored by Dominik Charousset's avatar Dominik Charousset

Fix stringifcation inspector and update to C++17

parent 739709a3
...@@ -86,71 +86,74 @@ public: ...@@ -86,71 +86,74 @@ public:
/// Prints a separator to the result string. /// Prints a separator to the result string.
void sep(); void sep();
void consume(string_view str); void consume(const timespan& x);
void consume(timespan x); void consume(const timestamp& x);
void consume(timestamp x); void consume(const bool& x);
void consume(bool x);
void consume(const void* ptr);
void consume(const char* cstr);
void consume(const std::vector<bool>& xs); void consume(const std::vector<bool>& xs);
template <class T> template <class T, size_t N>
enable_if_t<std::is_floating_point<T>::value> consume(T x) { void consume(const T (&xs)[N]) {
result_ += std::to_string(x); consume_range(xs, xs + N);
} }
template <class T> template <class T>
enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value> void consume(const T& x) {
consume(T x) { if constexpr (std::is_pointer<T>::value) {
consume_ptr(x);
} else if constexpr (std::is_convertible<T, string_view>::value) {
consume_str(string_view{x});
} else if constexpr (std::is_integral<T>::value) {
if constexpr (std::is_signed<T>::value)
consume_int(static_cast<int64_t>(x)); consume_int(static_cast<int64_t>(x));
} else
template <class T>
enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value>
consume(T x) {
consume_int(static_cast<uint64_t>(x)); consume_int(static_cast<uint64_t>(x));
} else if constexpr (std::is_floating_point<T>::value) {
result_ += std::to_string(x);
} else if constexpr (has_to_string<T>::value) {
result_ += to_string(x);
} else if constexpr (is_inspectable<stringification_inspector, T>::value) {
inspect(*this, const_cast<T&>(x));
} else if constexpr (is_map_like<T>::value) {
result_ += '{';
for (const auto& kvp : x) {
sep();
consume(kvp.first);
result_ += " = ";
consume(kvp.second);
}
result_ += '}';
} else if constexpr (is_iterable<T>::value) {
consume_range(x.begin(), x.end());
} else if constexpr (has_peek_all<T>::value) {
result_ += '[';
x.peek_all(*this);
result_ += ']';
} else {
result_ += "<unprintable>";
}
} }
template <class Clock, class Duration> template <class Clock, class Duration>
void consume(std::chrono::time_point<Clock, Duration> x) { void consume(const std::chrono::time_point<Clock, Duration>& x) {
timestamp tmp{std::chrono::duration_cast<timespan>(x.time_since_epoch())}; timestamp tmp{std::chrono::duration_cast<timespan>(x.time_since_epoch())};
consume(tmp); consume(tmp);
} }
template <class Rep, class Period> template <class Rep, class Period>
void consume(std::chrono::duration<Rep, Period> x) { void consume(const std::chrono::duration<Rep, Period>& x) {
auto tmp = std::chrono::duration_cast<timespan>(x); auto tmp = std::chrono::duration_cast<timespan>(x);
consume(tmp); consume(tmp);
} }
// Unwrap std::ref. // Unwrap std::ref.
template <class T> template <class T>
void consume(std::reference_wrapper<T> x) { void consume(const std::reference_wrapper<T>& x) {
return consume(x.get()); return consume(x.get());
} }
/// Picks up user-defined `to_string` functions.
template <class T>
enable_if_t<!std::is_pointer<T>::value && has_to_string<T>::value>
consume(const T& x) {
result_ += to_string(x);
}
/// Delegates to `inspect(*this, x)` if available and `T` does not provide
/// a `to_string` overload.
template <class T>
enable_if_t<is_inspectable<stringification_inspector, T>::value
&& !has_to_string<T>::value>
consume(const T& x) {
inspect(*this, const_cast<T&>(x));
}
template <class F, class S> template <class F, class S>
void consume(const std::pair<F, S>& x) { void consume(const std::pair<F, S>& x) {
result_ += '('; result_ += '(';
...@@ -165,81 +168,6 @@ public: ...@@ -165,81 +168,6 @@ public:
result_ += ')'; result_ += ')';
} }
template <class T>
enable_if_t<is_map_like<T>::value
&& !is_inspectable<stringification_inspector, T>::value
&& !has_to_string<T>::value>
consume(const T& xs) {
result_ += '{';
for (const auto& kvp : xs) {
sep();
consume(kvp.first);
result_ += " = ";
consume(kvp.second);
}
result_ += '}';
}
template <class Iterator>
void consume_range(Iterator first, Iterator last) {
result_ += '[';
while (first != last) {
sep();
consume(*first++);
}
result_ += ']';
}
template <class T>
enable_if_t<is_iterable<T>::value && !is_map_like<T>::value
&& !std::is_convertible<T, string_view>::value
&& !is_inspectable<stringification_inspector, T>::value
&& !has_to_string<T>::value>
consume(const T& xs) {
consume_range(xs.begin(), xs.end());
}
template <class T, size_t S>
void consume(const T (&xs)[S]) {
return consume_range(xs, xs + S);
}
template <class T>
enable_if_t<has_peek_all<T>::value
&& !is_iterable<T>::value // pick begin()/end() over peek_all
&& !is_inspectable<stringification_inspector, T>::value
&& !has_to_string<T>::value>
consume(const T& xs) {
result_ += '[';
xs.peek_all(*this);
result_ += ']';
}
template <class T>
enable_if_t<
std::is_pointer<T>::value
&& !std::is_same<void, typename std::remove_pointer<T>::type>::value>
consume(const T ptr) {
if (ptr) {
result_ += '*';
consume(*ptr);
} else {
result_ += "<null>";
}
}
/// Fallback printing `<unprintable>`.
template <class T>
enable_if_t<!is_iterable<T>::value && !has_peek_all<T>::value
&& !std::is_pointer<T>::value
&& !is_inspectable<stringification_inspector, T>::value
&& !std::is_arithmetic<T>::value
&& !std::is_convertible<T, string_view>::value
&& !has_to_string<T>::value>
consume(const T&) {
result_ += "<unprintable>";
}
void traverse() { void traverse() {
// end of recursion // end of recursion
} }
...@@ -306,6 +234,32 @@ public: ...@@ -306,6 +234,32 @@ public:
} }
private: private:
template <class Iterator>
void consume_range(Iterator first, Iterator last) {
result_ += '[';
while (first != last) {
sep();
consume(*first++);
}
result_ += ']';
}
template <class T>
void consume_ptr(const T* ptr) {
if (ptr) {
result_ += '*';
consume(*ptr);
} else {
result_ += "nullptr";
}
}
void consume_str(string_view str);
void consume_ptr(const void* ptr);
void consume_ptr(const char* cstr);
void consume_int(int64_t x); void consume_int(int64_t x);
void consume_int(uint64_t x); void consume_int(uint64_t x);
......
...@@ -60,24 +60,7 @@ void stringification_inspector::sep() { ...@@ -60,24 +60,7 @@ void stringification_inspector::sep() {
} }
} }
void stringification_inspector::consume(string_view str) { void stringification_inspector::consume(const timespan& x) {
if (str.empty()) {
result_ += R"("")";
return;
}
if (str[0] == '"') {
// Assume an already escaped string.
result_.insert(result_.end(), str.begin(), str.end());
return;
}
// Escape string.
result_ += '"';
for (char c : str)
escape(result_, c);
result_ += '"';
}
void stringification_inspector::consume(timespan x) {
auto ns = x.count(); auto ns = x.count();
if (ns % 1000 > 0) { if (ns % 1000 > 0) {
consume(ns); consume(ns);
...@@ -119,7 +102,7 @@ void stringification_inspector::consume(timespan x) { ...@@ -119,7 +102,7 @@ void stringification_inspector::consume(timespan x) {
result_ += "d"; result_ += "d";
} }
void stringification_inspector::consume(timestamp x) { void stringification_inspector::consume(const timestamp& x) {
char buf[64]; char buf[64];
auto y = std::chrono::time_point_cast<timestamp::clock::duration>(x); auto y = std::chrono::time_point_cast<timestamp::clock::duration>(x);
auto z = timestamp::clock::to_time_t(y); auto z = timestamp::clock::to_time_t(y);
...@@ -134,16 +117,42 @@ void stringification_inspector::consume(timestamp x) { ...@@ -134,16 +117,42 @@ void stringification_inspector::consume(timestamp x) {
result_ += frac; result_ += frac;
} }
void stringification_inspector::consume(bool x) { void stringification_inspector::consume(const bool& x) {
result_ += x ? "true" : "false"; result_ += x ? "true" : "false";
} }
void stringification_inspector::consume(const void* ptr) { void stringification_inspector::consume_str(string_view str) {
if (str.empty()) {
result_ += R"("")";
return;
}
if (str[0] == '"') {
// Assume an already escaped string.
result_.insert(result_.end(), str.begin(), str.end());
return;
}
// Escape string.
result_ += '"';
for (char c : str)
escape(result_, c);
result_ += '"';
}
void stringification_inspector::consume(const std::vector<bool>& xs) {
result_ += '[';
for (bool x : xs) {
sep();
consume(x);
}
result_ += ']';
}
void stringification_inspector::consume_ptr(const void* ptr) {
result_ += "0x"; result_ += "0x";
consume(reinterpret_cast<intptr_t>(ptr)); consume(reinterpret_cast<intptr_t>(ptr));
} }
void stringification_inspector::consume(const char* cstr) { void stringification_inspector::consume_ptr(const char* cstr) {
if (cstr == nullptr) { if (cstr == nullptr) {
result_ += "<null>"; result_ += "<null>";
return; return;
...@@ -164,15 +173,6 @@ void stringification_inspector::consume(const char* cstr) { ...@@ -164,15 +173,6 @@ void stringification_inspector::consume(const char* cstr) {
result_ += '"'; result_ += '"';
} }
void stringification_inspector::consume(const std::vector<bool>& xs) {
result_ += '[';
for (bool x : xs) {
sep();
consume(x);
}
result_ += ']';
}
void stringification_inspector::consume_int(int64_t x) { void stringification_inspector::consume_int(int64_t x) {
if (x >= 0) if (x >= 0)
return consume_int(static_cast<uint64_t>(x)); return consume_int(static_cast<uint64_t>(x));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment