From 86287b8d5625ef390da6ef10fc77a872b8ad41ac Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 21 Oct 2020 16:27:42 -0700 Subject: [PATCH] Optimize common case in parse_format_specs --- include/fmt/format.h | 23 ++++++++++++++++------- test/format-test.cc | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 17ee90a6..388c8439 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2739,14 +2739,13 @@ FMT_CONSTEXPR int code_point_length(const Char* begin) { return len + !len; } -// Converts a character to the underlying integral type. +// Converts a character to ASCII. Returns a number > 127 on conversion failure. template ::value)> -constexpr Char to_integral(Char value) { +constexpr Char to_ascii(Char value) { return value; } - template ::value)> -constexpr typename std::underlying_type::type to_integral(Char value) { +constexpr typename std::underlying_type::type to_ascii(Char value) { return value; } @@ -2759,7 +2758,7 @@ FMT_CONSTEXPR const Char* parse_align(const Char* begin, const Char* end, auto p = begin + code_point_length(begin); if (p >= end) p = begin; for (;;) { - switch (to_integral(*p)) { + switch (to_ascii(*p)) { case '<': align = align::left; break; @@ -2833,18 +2832,28 @@ FMT_CONSTEXPR const Char* parse_precision(const Char* begin, const Char* end, return begin; } +template +constexpr bool is_ascii_letter(Char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + // Parses standard format specifiers and sends notifications about parsed // components to handler. template FMT_CONSTEXPR const Char* parse_format_specs(const Char* begin, const Char* end, SpecHandler&& handler) { - if (begin == end || *begin == '}') return begin; + if (begin == end) return begin; + + if (is_ascii_letter(*begin) && (begin + 1 == end || begin[1] == '}')) { + handler.on_type(*begin++); + return begin; + } begin = parse_align(begin, end, handler); if (begin == end) return begin; // Parse sign. - switch (to_integral(*begin)) { + switch (to_ascii(*begin)) { case '+': handler.on_plus(); ++begin; diff --git a/test/format-test.cc b/test/format-test.cc index 40a0137b..128b57a2 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2423,7 +2423,7 @@ struct custom_char { operator int() const { return value; } }; -int to_integral(custom_char c) { return c; } +int to_ascii(custom_char c) { return c; } FMT_BEGIN_NAMESPACE template <> struct is_char : std::true_type {};