From 2caf1b3b91f6d56f420cec8bf752f9af26aa51af Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 21 Jan 2024 07:56:56 -0800 Subject: [PATCH] scan more --- test/scan.h | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/test/scan.h b/test/scan.h index 19e9572d..59f41f77 100644 --- a/test/scan.h +++ b/test/scan.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "fmt/format.h" @@ -549,6 +550,11 @@ struct scan_handler { void on_error(const char* message) { report_error(message); } }; + +void vscan(detail::scan_buffer& buf, string_view fmt, scan_args args) { + auto h = detail::scan_handler(fmt, buf, args); + detail::parse_format_string(fmt, h); +} } // namespace detail template @@ -556,18 +562,22 @@ auto make_scan_args(T&... args) -> std::array { return {{args...}}; } -template class scan_value { +template class scan_data { private: - T value_; + std::tuple values_; public: - scan_value(T value) : value_(std::move(value)) {} + scan_data(T... values) : values_(std::move(values)...) {} - auto value() const -> const T& { return value_; } + auto value() const -> decltype(std::get<0>(values_)) { + return std::get<0>(values_); + } }; +class scan_error {}; + // A rudimentary version of std::expected for testing the API shape. -template class expected { +template class expected { private: T value_; @@ -577,20 +587,21 @@ template class expected { auto operator->() const -> const T* { return &value_; } }; -template using scan_result = expected>; +template +using scan_result = expected, scan_error>; -void vscan(detail::scan_buffer& buf, string_view fmt, scan_args args) { - auto h = detail::scan_handler(fmt, buf, args); - detail::parse_format_string(fmt, h); +auto vscan(string_view input, string_view fmt, scan_args args) + -> string_view::iterator { + auto&& buf = detail::string_scan_buffer(input); + detail::vscan(buf, fmt, args); + return input.begin() + (buf.begin().base() - input.data()); } // Scans the input and stores the results (in)to args. template auto scan_to(string_view input, string_view fmt, T&... args) -> string_view::iterator { - auto&& buf = detail::string_scan_buffer(input); - vscan(buf, fmt, make_scan_args(args...)); - return input.begin() + (buf.begin().base() - input.data()); + return vscan(input, fmt, make_scan_args(args...)); } template @@ -598,22 +609,22 @@ auto scan(string_view input, string_view fmt) -> scan_result { static_assert(std::is_same, T>::value, ""); auto value = T(); scan_to(input, fmt, value); - return scan_value(std::move(value)); + return scan_data(std::move(value)); } -template ::value)> -auto scan_to(InputRange&& input, string_view fmt, T&... args) +template ::value)> +auto scan_to(Range&& input, string_view fmt, T&... args) -> decltype(std::begin(input)) { auto it = std::begin(input); - vscan(get_buffer(it), fmt, make_scan_args(args...)); + detail::vscan(get_buffer(it), fmt, make_scan_args(args...)); return it; } template auto scan_to(FILE* f, string_view fmt, T&... args) -> bool { auto&& buf = detail::file_scan_buffer(f); - vscan(buf, fmt, make_scan_args(args...)); + detail::vscan(buf, fmt, make_scan_args(args...)); return buf.begin() != buf.end(); }