forked from fmtlib/fmt
scan more
This commit is contained in:
47
test/scan.h
47
test/scan.h
@@ -8,6 +8,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
|
||||||
@@ -549,6 +550,11 @@ struct scan_handler {
|
|||||||
|
|
||||||
void on_error(const char* message) { report_error(message); }
|
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<false>(fmt, h);
|
||||||
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
@@ -556,18 +562,22 @@ auto make_scan_args(T&... args) -> std::array<scan_arg, sizeof...(T)> {
|
|||||||
return {{args...}};
|
return {{args...}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> class scan_value {
|
template <typename... T> class scan_data {
|
||||||
private:
|
private:
|
||||||
T value_;
|
std::tuple<T...> values_;
|
||||||
|
|
||||||
public:
|
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.
|
// A rudimentary version of std::expected for testing the API shape.
|
||||||
template <typename T> class expected {
|
template <typename T, typename E> class expected {
|
||||||
private:
|
private:
|
||||||
T value_;
|
T value_;
|
||||||
|
|
||||||
@@ -577,20 +587,21 @@ template <typename T> class expected {
|
|||||||
auto operator->() const -> const T* { return &value_; }
|
auto operator->() const -> const T* { return &value_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> using scan_result = expected<scan_value<T>>;
|
template <typename... T>
|
||||||
|
using scan_result = expected<scan_data<T...>, scan_error>;
|
||||||
|
|
||||||
void vscan(detail::scan_buffer& buf, string_view fmt, scan_args args) {
|
auto vscan(string_view input, string_view fmt, scan_args args)
|
||||||
auto h = detail::scan_handler(fmt, buf, args);
|
-> string_view::iterator {
|
||||||
detail::parse_format_string<false>(fmt, h);
|
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.
|
// Scans the input and stores the results (in)to args.
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
auto scan_to(string_view input, string_view fmt, T&... args)
|
auto scan_to(string_view input, string_view fmt, T&... args)
|
||||||
-> string_view::iterator {
|
-> string_view::iterator {
|
||||||
auto&& buf = detail::string_scan_buffer(input);
|
return vscan(input, fmt, make_scan_args(args...));
|
||||||
vscan(buf, fmt, make_scan_args(args...));
|
|
||||||
return input.begin() + (buf.begin().base() - input.data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -598,22 +609,22 @@ auto scan(string_view input, string_view fmt) -> scan_result<T> {
|
|||||||
static_assert(std::is_same<remove_cvref_t<T>, T>::value, "");
|
static_assert(std::is_same<remove_cvref_t<T>, T>::value, "");
|
||||||
auto value = T();
|
auto value = T();
|
||||||
scan_to(input, fmt, value);
|
scan_to(input, fmt, value);
|
||||||
return scan_value<T>(std::move(value));
|
return scan_data<T>(std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputRange, typename... T,
|
template <typename Range, typename... T,
|
||||||
FMT_ENABLE_IF(!std::is_convertible<InputRange, string_view>::value)>
|
FMT_ENABLE_IF(!std::is_convertible<Range, string_view>::value)>
|
||||||
auto scan_to(InputRange&& input, string_view fmt, T&... args)
|
auto scan_to(Range&& input, string_view fmt, T&... args)
|
||||||
-> decltype(std::begin(input)) {
|
-> decltype(std::begin(input)) {
|
||||||
auto it = 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;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
auto scan_to(FILE* f, string_view fmt, T&... args) -> bool {
|
auto scan_to(FILE* f, string_view fmt, T&... args) -> bool {
|
||||||
auto&& buf = detail::file_scan_buffer(f);
|
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();
|
return buf.begin() != buf.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user