forked from fmtlib/fmt
Improve iterator handling in scan
This commit is contained in:
30
test/scan.h
30
test/scan.h
@@ -395,8 +395,10 @@ struct scan_handler : error_handler {
|
|||||||
int next_arg_id_;
|
int next_arg_id_;
|
||||||
scan_arg arg_;
|
scan_arg arg_;
|
||||||
|
|
||||||
template <typename T = unsigned> auto read_uint() -> optional<T> {
|
using iterator = scan_buffer::iterator;
|
||||||
auto it = scan_ctx_.begin(), end = scan_ctx_.end();
|
|
||||||
|
template <typename T = unsigned> auto read_uint(iterator& it) -> optional<T> {
|
||||||
|
auto end = scan_ctx_.end();
|
||||||
if (it == end) return {};
|
if (it == end) return {};
|
||||||
char c = *it;
|
char c = *it;
|
||||||
if (c < '0' || c > '9') on_error("invalid input");
|
if (c < '0' || c > '9') on_error("invalid input");
|
||||||
@@ -412,7 +414,6 @@ struct scan_handler : error_handler {
|
|||||||
++num_digits;
|
++num_digits;
|
||||||
if (c < '0' || c > '9') break;
|
if (c < '0' || c > '9') break;
|
||||||
} while (it != end);
|
} while (it != end);
|
||||||
scan_ctx_.advance_to(it);
|
|
||||||
|
|
||||||
// Check overflow.
|
// Check overflow.
|
||||||
if (num_digits <= std::numeric_limits<int>::digits10) return value;
|
if (num_digits <= std::numeric_limits<int>::digits10) return value;
|
||||||
@@ -424,14 +425,11 @@ struct scan_handler : error_handler {
|
|||||||
throw format_error("number is too big");
|
throw format_error("number is too big");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = int> auto read_int() -> optional<T> {
|
template <typename T = int> auto read_int(iterator& it) -> optional<T> {
|
||||||
auto it = scan_ctx_.begin(), end = scan_ctx_.end();
|
auto end = scan_ctx_.end();
|
||||||
bool negative = it != end && *it == '-';
|
bool negative = it != end && *it == '-';
|
||||||
if (negative) {
|
if (negative) ++it;
|
||||||
++it;
|
if (auto abs_value = read_uint<typename std::make_unsigned<T>::type>(it)) {
|
||||||
scan_ctx_.advance_to(it);
|
|
||||||
}
|
|
||||||
if (auto abs_value = read_uint<typename std::make_unsigned<T>::type>()) {
|
|
||||||
auto value = static_cast<T>(*abs_value);
|
auto value = static_cast<T>(*abs_value);
|
||||||
return negative ? -value : value;
|
return negative ? -value : value;
|
||||||
}
|
}
|
||||||
@@ -469,24 +467,22 @@ struct scan_handler : error_handler {
|
|||||||
void on_replacement_field(int, const char*) {
|
void on_replacement_field(int, const char*) {
|
||||||
auto it = scan_ctx_.begin(), end = scan_ctx_.end();
|
auto it = scan_ctx_.begin(), end = scan_ctx_.end();
|
||||||
while (it != end && is_whitespace(*it)) ++it;
|
while (it != end && is_whitespace(*it)) ++it;
|
||||||
scan_ctx_.advance_to(it);
|
|
||||||
switch (arg_.type) {
|
switch (arg_.type) {
|
||||||
case scan_type::int_type:
|
case scan_type::int_type:
|
||||||
if (auto value = read_int()) *arg_.int_value = *value;
|
if (auto value = read_int(it)) *arg_.int_value = *value;
|
||||||
break;
|
break;
|
||||||
case scan_type::uint_type:
|
case scan_type::uint_type:
|
||||||
if (auto value = read_uint()) *arg_.uint_value = *value;
|
if (auto value = read_uint(it)) *arg_.uint_value = *value;
|
||||||
break;
|
break;
|
||||||
case scan_type::long_long_type:
|
case scan_type::long_long_type:
|
||||||
if (auto value = read_int<long long>()) *arg_.long_long_value = *value;
|
if (auto value = read_int<long long>(it)) *arg_.long_long_value = *value;
|
||||||
break;
|
break;
|
||||||
case scan_type::ulong_long_type:
|
case scan_type::ulong_long_type:
|
||||||
if (auto value = read_uint<unsigned long long>())
|
if (auto value = read_uint<unsigned long long>(it))
|
||||||
*arg_.ulong_long_value = *value;
|
*arg_.ulong_long_value = *value;
|
||||||
break;
|
break;
|
||||||
case scan_type::string_type:
|
case scan_type::string_type:
|
||||||
while (it != end && *it != ' ') arg_.string->push_back(*it++);
|
while (it != end && *it != ' ') arg_.string->push_back(*it++);
|
||||||
scan_ctx_.advance_to(it);
|
|
||||||
break;
|
break;
|
||||||
case scan_type::string_view_type: {
|
case scan_type::string_view_type: {
|
||||||
auto range = to_contiguous(it);
|
auto range = to_contiguous(it);
|
||||||
@@ -497,13 +493,13 @@ struct scan_handler : error_handler {
|
|||||||
size_t size = to_unsigned(p - range.begin);
|
size_t size = to_unsigned(p - range.begin);
|
||||||
*arg_.string_view = {range.begin, size};
|
*arg_.string_view = {range.begin, size};
|
||||||
advance(it, size);
|
advance(it, size);
|
||||||
scan_ctx_.advance_to(it);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case scan_type::none_type:
|
case scan_type::none_type:
|
||||||
case scan_type::custom_type:
|
case scan_type::custom_type:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
scan_ctx_.advance_to(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto on_format_specs(int, const char* begin, const char*) -> const char* {
|
auto on_format_specs(int, const char* begin, const char*) -> const char* {
|
||||||
|
Reference in New Issue
Block a user