forked from fmtlib/fmt
Implement parsing of string_views
This commit is contained in:
@ -14,25 +14,40 @@
|
|||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
enum class scan_type {
|
||||||
|
none_type,
|
||||||
|
int_type,
|
||||||
|
uint_type,
|
||||||
|
long_long_type,
|
||||||
|
ulong_long_type,
|
||||||
|
string_type,
|
||||||
|
string_view_type
|
||||||
|
};
|
||||||
|
|
||||||
struct scan_arg {
|
struct scan_arg {
|
||||||
type arg_type;
|
scan_type arg_type;
|
||||||
union {
|
union {
|
||||||
int* int_value;
|
int* int_value;
|
||||||
unsigned* uint_value;
|
unsigned* uint_value;
|
||||||
long long* long_long_value;
|
long long* long_long_value;
|
||||||
unsigned long long* ulong_long_value;
|
unsigned long long* ulong_long_value;
|
||||||
std::string* string;
|
std::string* string;
|
||||||
|
fmt::string_view* string_view;
|
||||||
// TODO: more types
|
// TODO: more types
|
||||||
};
|
};
|
||||||
|
|
||||||
scan_arg() : arg_type(none_type) {}
|
scan_arg() : arg_type(scan_type::none_type) {}
|
||||||
scan_arg(int& value) : arg_type(int_type), int_value(&value) {}
|
scan_arg(int& value) : arg_type(scan_type::int_type), int_value(&value) {}
|
||||||
scan_arg(unsigned& value) : arg_type(uint_type), uint_value(&value) {}
|
scan_arg(unsigned& value)
|
||||||
|
: arg_type(scan_type::uint_type), uint_value(&value) {}
|
||||||
scan_arg(long long& value)
|
scan_arg(long long& value)
|
||||||
: arg_type(long_long_type), long_long_value(&value) {}
|
: arg_type(scan_type::long_long_type), long_long_value(&value) {}
|
||||||
scan_arg(unsigned long long& value)
|
scan_arg(unsigned long long& value)
|
||||||
: arg_type(ulong_long_type), ulong_long_value(&value) {}
|
: arg_type(scan_type::ulong_long_type), ulong_long_value(&value) {}
|
||||||
scan_arg(std::string& value) : arg_type(string_type), string(&value) {}
|
scan_arg(std::string& value)
|
||||||
|
: arg_type(scan_type::string_type), string(&value) {}
|
||||||
|
scan_arg(fmt::string_view& value)
|
||||||
|
: arg_type(scan_type::string_view_type), string_view(&value) {}
|
||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
@ -102,22 +117,28 @@ struct scan_handler : error_handler {
|
|||||||
|
|
||||||
void on_replacement_field(const char*) {
|
void on_replacement_field(const char*) {
|
||||||
switch (arg_.arg_type) {
|
switch (arg_.arg_type) {
|
||||||
case int_type:
|
case scan_type::int_type:
|
||||||
*arg_.int_value = read_int();
|
*arg_.int_value = read_int();
|
||||||
break;
|
break;
|
||||||
case uint_type:
|
case scan_type::uint_type:
|
||||||
*arg_.uint_value = read_uint();
|
*arg_.uint_value = read_uint();
|
||||||
break;
|
break;
|
||||||
case long_long_type:
|
case scan_type::long_long_type:
|
||||||
*arg_.long_long_value = read_int<long long>();
|
*arg_.long_long_value = read_int<long long>();
|
||||||
break;
|
break;
|
||||||
case ulong_long_type:
|
case scan_type::ulong_long_type:
|
||||||
*arg_.ulong_long_value = read_uint<unsigned long long>();
|
*arg_.ulong_long_value = read_uint<unsigned long long>();
|
||||||
break;
|
break;
|
||||||
case string_type: {
|
case scan_type::string_type:
|
||||||
while (begin_ != end_ && *begin_ != ' ')
|
while (begin_ != end_ && *begin_ != ' ')
|
||||||
arg_.string->push_back(*begin_++);
|
arg_.string->push_back(*begin_++);
|
||||||
break;
|
break;
|
||||||
|
case scan_type::string_view_type: {
|
||||||
|
auto s = begin_;
|
||||||
|
while (begin_ != end_ && *begin_ != ' ')
|
||||||
|
++begin_;
|
||||||
|
*arg_.string_view = fmt::string_view(s, begin_ - s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -185,12 +206,19 @@ TEST(ScanTest, ReadULongLong) {
|
|||||||
EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error,
|
EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error,
|
||||||
"invalid input");
|
"invalid input");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ScanTest, ReadString) {
|
TEST(ScanTest, ReadString) {
|
||||||
std::string s;
|
std::string s;
|
||||||
fmt::scan("foo", "{}", s);
|
fmt::scan("foo", "{}", s);
|
||||||
EXPECT_EQ(s, "foo");
|
EXPECT_EQ(s, "foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ScanTest, ReadStringView) {
|
||||||
|
fmt::string_view s;
|
||||||
|
fmt::scan("foo", "{}", s);
|
||||||
|
EXPECT_EQ(s, "foo");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ScanTest, InvalidFormat) {
|
TEST(ScanTest, InvalidFormat) {
|
||||||
EXPECT_THROW_MSG(fmt::scan("", "{}"), fmt::format_error,
|
EXPECT_THROW_MSG(fmt::scan("", "{}"), fmt::format_error,
|
||||||
"argument index out of range");
|
"argument index out of range");
|
||||||
|
Reference in New Issue
Block a user