Simplify arg_formatter_base

This commit is contained in:
Victor Zverovich 2020-05-29 09:10:08 -07:00
parent ac8dfd841f
commit 519571edec
5 changed files with 46 additions and 35 deletions

View File

@ -200,7 +200,8 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
ec = 1;
return {};
}
const auto min1 = (std::numeric_limits<IntermediateRep>::min)() / Factor::num;
const auto min1 =
(std::numeric_limits<IntermediateRep>::min)() / Factor::num;
if (count < min1) {
ec = 1;
return {};

View File

@ -886,6 +886,13 @@ template <> inline wchar_t decimal_point(locale_ref loc) {
return decimal_point_impl<wchar_t>(loc);
}
template <typename Char> bool equal2(const Char* lhs, const char* rhs) {
return lhs[0] == rhs[0] && lhs[1] == rhs[1];
}
inline bool equal2(const char* lhs, const char* rhs) {
return memcmp(lhs, rhs, 2) == 0;
}
template <typename Char> void copy2(Char* dst, const char* src) {
*dst++ = static_cast<Char>(*src++);
*dst = static_cast<Char>(*src);
@ -1677,11 +1684,12 @@ template <typename T> struct is_integral : std::is_integral<T> {};
template <> struct is_integral<int128_t> : std::true_type {};
template <> struct is_integral<uint128_t> : std::true_type {};
template <typename Range, typename ErrorHandler = detail::error_handler>
template <typename OutputIt, typename Char,
typename ErrorHandler = detail::error_handler>
class arg_formatter_base {
public:
using char_type = typename Range::value_type;
using iterator = typename Range::iterator;
using char_type = Char;
using iterator = OutputIt;
using format_specs = basic_format_specs<char_type>;
private:
@ -1753,8 +1761,8 @@ class arg_formatter_base {
*it++ = value;
}
template <typename Char, FMT_ENABLE_IF(std::is_same<Char, char_type>::value)>
void write(Char value) {
template <typename Ch, FMT_ENABLE_IF(std::is_same<Ch, char_type>::value)>
void write(Ch value) {
auto&& it = reserve(1);
*it++ = value;
}
@ -1769,18 +1777,18 @@ class arg_formatter_base {
it = std::copy(value.begin(), value.end(), it);
}
template <typename Char>
void write(const Char* s, size_t size, const format_specs& specs) {
template <typename Ch>
void write(const Ch* s, size_t size, const format_specs& specs) {
auto width = specs.width != 0
? count_code_points(basic_string_view<Char>(s, size))
? count_code_points(basic_string_view<Ch>(s, size))
: 0;
out_ = write_padded(out_, specs, size, width, [=](reserve_iterator it) {
return copy_str<char_type>(s, s + size, it);
});
}
template <typename Char>
void write(basic_string_view<Char> s, const format_specs& specs = {}) {
template <typename Ch>
void write(basic_string_view<Ch> s, const format_specs& specs = {}) {
out_ = detail::write(out_, s, specs);
}
@ -1808,8 +1816,8 @@ class arg_formatter_base {
}
public:
arg_formatter_base(Range r, format_specs* s, locale_ref loc)
: out_(r.begin()), locale_(loc), specs_(s) {}
arg_formatter_base(OutputIt out, format_specs* s, locale_ref loc)
: out_(out), locale_(loc), specs_(s) {}
iterator operator()(monostate) {
FMT_ASSERT(false, "invalid argument type");
@ -2716,10 +2724,13 @@ FMT_API void report_error(format_func func, int error_code,
/** The default argument formatter. */
template <typename Range>
class arg_formatter : public detail::arg_formatter_base<Range> {
class arg_formatter
: public detail::arg_formatter_base<typename Range::iterator,
typename Range::value_type> {
private:
using char_type = typename Range::value_type;
using base = detail::arg_formatter_base<Range>;
using base = detail::arg_formatter_base<typename Range::iterator,
typename Range::value_type>;
using context_type = basic_format_context<typename base::iterator, char_type>;
context_type& ctx_;
@ -2741,7 +2752,7 @@ class arg_formatter : public detail::arg_formatter_base<Range> {
context_type& ctx,
basic_format_parse_context<char_type>* parse_ctx = nullptr,
format_specs* specs = nullptr)
: base(Range(ctx.out()), specs, ctx.locale()),
: base(ctx.out(), specs, ctx.locale()),
ctx_(ctx),
parse_ctx_(parse_ctx) {}
@ -3156,13 +3167,6 @@ struct format_handler : detail::error_handler {
basic_format_arg<Context> arg;
};
template <typename Char> bool equal2(const Char* lhs, const char* rhs) {
return lhs[0] == rhs[0] && lhs[1] == rhs[1];
}
inline bool equal2(const char* lhs, const char* rhs) {
return memcmp(lhs, rhs, 2) == 0;
}
/** Formats arguments and writes the output to the range. */
template <typename ArgFormatter, typename Char, typename Context>
typename Context::iterator vformat_to(
@ -3170,7 +3174,7 @@ typename Context::iterator vformat_to(
basic_format_args<Context> args,
detail::locale_ref loc = detail::locale_ref()) {
format_handler<ArgFormatter, Char, Context> h(out, format_str, args, loc);
if (format_str.size() == 2 && equal2(format_str.data(), "{}")) {
if (format_str.size() == 2 && detail::equal2(format_str.data(), "{}")) {
auto arg = detail::get_arg(h.context, 0);
h.parse_context.advance_to(&format_str[1]);
return visit_format_arg(ArgFormatter(h.context, &h.parse_context), arg);

View File

@ -208,13 +208,16 @@ template <typename OutputIt, typename Char> class basic_printf_context;
\endrst
*/
template <typename Range>
class printf_arg_formatter : public detail::arg_formatter_base<Range> {
class printf_arg_formatter
: public detail::arg_formatter_base<typename Range::iterator,
typename Range::value_type> {
public:
using iterator = typename Range::iterator;
private:
using char_type = typename Range::value_type;
using base = detail::arg_formatter_base<Range>;
using base = detail::arg_formatter_base<typename Range::iterator,
typename Range::value_type>;
using context_type = basic_printf_context<iterator, char_type>;
context_type& context_;
@ -240,7 +243,7 @@ class printf_arg_formatter : public detail::arg_formatter_base<Range> {
\endrst
*/
printf_arg_formatter(iterator iter, format_specs& specs, context_type& ctx)
: base(Range(iter), &specs, detail::locale_ref()), context_(ctx) {}
: base(iter, &specs, detail::locale_ref()), context_(ctx) {}
template <typename T, FMT_ENABLE_IF(fmt::detail::is_integral<T>::value)>
iterator operator()(T value) {
@ -512,7 +515,8 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
// For d, i, o, u, x, and X conversion specifiers, if a precision is
// specified, the '0' flag is ignored
if (specs.precision >= 0 && arg.is_integral())
specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types or if '-' present.
specs.fill[0] =
' '; // Ignore '0' flag for non-numeric types or if '-' present.
if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) {
auto str = visit_format_arg(detail::get_cstring<Char>(), arg);
auto str_end = str + specs.precision;

View File

@ -490,10 +490,12 @@ namespace detail {
template <typename Range>
class arg_formatter
: public fmt::internal::arg_formatter_base<Range, error_handler> {
: public fmt::internal::arg_formatter_base<
typename Range::iterator, typename Range::value_type, error_handler> {
private:
using char_type = typename Range::value_type;
using base = fmt::internal::arg_formatter_base<Range, error_handler>;
using base = fmt::internal::arg_formatter_base<
typename Range::iterator, char_type, error_handler>;
using format_context = std::basic_format_context<typename base::iterator, char_type>;
using parse_context = basic_format_parse_context<char_type>;
@ -513,7 +515,7 @@ class arg_formatter
\endrst
*/
arg_formatter(format_context& ctx, parse_context* parse_ctx = nullptr, fmt::format_specs* spec = nullptr)
: base(Range(ctx.out()), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {}
: base(ctx.out(), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {}
using base::operator();

View File

@ -1809,7 +1809,7 @@ TEST(FormatTest, StrongEnum) {
using buffer_range = fmt::buffer_range<char>;
class mock_arg_formatter
: public fmt::detail::arg_formatter_base<buffer_range> {
: public fmt::detail::arg_formatter_base<buffer_range::iterator, char> {
private:
#if FMT_USE_INT128
MOCK_METHOD1(call, void(__int128_t value));
@ -1818,12 +1818,12 @@ class mock_arg_formatter
#endif
public:
typedef fmt::detail::arg_formatter_base<buffer_range> base;
typedef fmt::detail::arg_formatter_base<buffer_range::iterator, char> base;
typedef buffer_range range;
mock_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context*,
fmt::format_specs* s = nullptr)
: base(fmt::detail::get_container(ctx.out()), s, ctx.locale()) {
: base(ctx.out(), s, ctx.locale()) {
EXPECT_CALL(*this, call(42));
}