Implement format_parse_context::starts_with()

Add method to check whether the format string starts with a given
prefix.
This commit is contained in:
Roberto Rossini 2023-06-02 22:26:22 +02:00
parent 8abfc145be
commit b23be10416
2 changed files with 29 additions and 4 deletions

View File

@ -675,6 +675,20 @@ template <typename Char> class basic_format_parse_context {
*/
constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
/**
* Checks whether the format string starts with the given prefix
*/
constexpr bool starts_with(iterator prefix) const noexcept {
auto first = begin();
auto last = end();
while (first != last && *prefix != '\0') {
if (*prefix++ != *first++) {
return false;
}
}
return *prefix == '\0';
}
/** Advances the begin iterator to ``it``. */
FMT_CONSTEXPR void advance_to(iterator it) {
format_str_.remove_prefix(detail::to_unsigned(it - begin()));

View File

@ -38,12 +38,23 @@ struct custom_type {
FMT_BEGIN_NAMESPACE
template <> struct formatter<custom_type> {
auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
private:
bool hex = false;
public:
auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
if (ctx.starts_with("hex")) {
hex = true;
return ctx.begin() + 3;
}
return ctx.begin();
}
template <typename FormatContext>
auto format(const custom_type& p, FormatContext& ctx) -> decltype(ctx.out()) {
if (hex) {
return fmt::format_to(ctx.out(), "cust={:x}", p.i);
}
return fmt::format_to(ctx.out(), "cust={}", p.i);
}
};
@ -57,9 +68,9 @@ TEST(args_test, custom_format) {
store.push_back(c);
++c.i;
store.push_back(std::cref(c));
++c.i;
auto result = fmt::vformat("{} and {} and {}", store);
EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
c.i = 15;
auto result = fmt::vformat("{} and {} and {:hex}", store);
EXPECT_EQ("cust=0 and cust=1 and cust=f", result);
}
struct to_stringable {