From 33b77a8722c3c809386ea28a11cedf4500bb6f10 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 3 Mar 2016 13:34:23 +1100 Subject: [PATCH] Reduce number of formatting template instantiations needed - should reduce compile time and executable size a bit Small run-time performance penalty shouldn't be a big deal --- src/lib/util/strformat.h | 137 ++++++++++++++------------------------- 1 file changed, 48 insertions(+), 89 deletions(-) diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h index ac7301dc6bd..f0f481bb3f3 100644 --- a/src/lib/util/strformat.h +++ b/src/lib/util/strformat.h @@ -1040,7 +1040,7 @@ public: { return (m_end && (m_end == it)) || (m_check_nul && (format_chars::nul == *it)); } - std::size_t size() const + std::size_t argument_count() const { return m_argument_count; } @@ -1131,6 +1131,9 @@ class format_argument_pack_impl , public format_argument_pack { public: + using typename format_argument_pack::iterator; + using format_argument_pack::operator[]; + template format_argument_pack_impl(Format &&fmt, Params &&... args) : std::array, Count>({ { format_argument(std::forward(args))... } }) @@ -1147,15 +1150,9 @@ public: //************************************************************************** -// ARGUMENT PACK CREATOR FUNCTIONS +// ARGUMENT PACK CREATOR FUNCTION //************************************************************************** -template -inline std::array, sizeof...(Params)> make_format_arguments(Params &&... args) -{ - return std::array, sizeof...(Params)>({ { format_argument(std::forward(args))... } }); -} - template inline format_argument_pack_impl make_format_argument_pack(Format &&fmt, Params &&... args) { @@ -1164,54 +1161,16 @@ inline format_argument_pack_impl make_format_argument //************************************************************************** -// FORMAT STRING PARSING HELPERS +// FORMAT STRING PARSING HELPER //************************************************************************** template -class format_helper_base : public format_chars()))> > > -{ -public: - typedef std::remove_reference_t()))> iterator; - static iterator begin(Format const &fmt) { return std::cbegin(fmt); } - static bool at_end(Format const &fmt, iterator const &it) { return std::cend(fmt) == it; } -}; - -template -class format_helper_base : public format_chars > -{ -public: - typedef Character const *iterator; - static iterator begin(Character const *fmt) { return fmt; } - static bool at_end(Character const *fmt, iterator const &it) { return format_helper_base::nul == *it; } -}; - -template -class format_helper_base : public format_chars > -{ -public: - typedef Character const *iterator; - static iterator begin(std::remove_const_t (&fmt)[Length]) { return std::cbegin(fmt); } - static iterator begin(std::add_const_t (&fmt)[Length]) { return std::cbegin(fmt); } - static bool at_end(std::remove_const_t (&fmt)[Length], iterator const &it) { return (std::cend(fmt) == it) || (format_chars::nul == *it); } - static bool at_end(std::add_const_t (&fmt)[Length], iterator const &it) { return (std::cend(fmt) == it) || (format_helper_base::nul == *it); } -}; - -template -class format_helper_base > : public format_chars::char_type> -{ -public: - typedef typename format_argument_pack::iterator iterator; - static iterator begin(format_argument_pack const &fmt) { return fmt.format_begin(); } - static bool at_end(format_argument_pack const &fmt, iterator const &it) { return fmt.format_at_end(it); } -}; - -template -class format_helper : public format_helper_base +class format_helper : public format_chars { public: static bool parse_format( Format const &fmt, - typename format_helper::iterator &it, + typename Format::iterator &it, format_flags &flags, int &next_position, int &argument_position, @@ -1219,7 +1178,7 @@ public: int &precision_position) { static_assert((format_helper::nine - format_helper::zero) == 9, "Digits must be contiguous"); - assert(!format_helper::at_end(fmt, it)); + assert(!fmt.format_at_end(it)); assert(format_helper::percent == *it); int num; @@ -1231,8 +1190,8 @@ public: precision_position = -1; // Leading zeroes are tricky - they could be a zero-pad flag or part of a position specifier - bool const leading_zero(!format_helper::at_end(fmt, it) && (format_helper::zero == *it)); - while (!format_helper::at_end(fmt, it) && (format_helper::zero == *it)) ++it; + bool const leading_zero(!fmt.format_at_end(it) && (format_helper::zero == *it)); + while (!fmt.format_at_end(it) && (format_helper::zero == *it)) ++it; // Digits encountered at this point could be a field width or a position specifier num = 0; @@ -1258,7 +1217,7 @@ public: } // Parse flag characters - while (!format_helper::at_end(fmt, it)) + while (!fmt.format_at_end(it)) { switch (*it) { @@ -1275,7 +1234,7 @@ public: } // Check for literal or parameterised field width - if (!format_helper::at_end(fmt, it)) + if (!fmt.format_at_end(it)) { if (is_digit(*it)) { @@ -1302,14 +1261,14 @@ public: } // Check for literal or parameterised precision - if (!format_helper::at_end(fmt, it) && (*it == format_helper::point)) + if (!fmt.format_at_end(it) && (*it == format_helper::point)) { ++it; if (have_digit(fmt, it)) { flags.set_precision(read_number(fmt, it)); } - else if (!format_helper::at_end(fmt, it) && (format_helper::asterisk == *it)) + else if (!fmt.format_at_end(it) && (format_helper::asterisk == *it)) { ++it; if (have_digit(fmt, it)) @@ -1333,11 +1292,11 @@ public: } // Check for length modifiers - if (!format_helper::at_end(fmt, it)) switch (*it) + if (!fmt.format_at_end(it)) switch (*it) { case format_helper::h: ++it; - if (!format_helper::at_end(fmt, it) && (format_helper::h == *it)) + if (!fmt.format_at_end(it) && (format_helper::h == *it)) { ++it; flags.set_length(format_flags::length::character); @@ -1349,7 +1308,7 @@ public: break; case format_helper::l: ++it; - if (!format_helper::at_end(fmt, it) && (format_helper::l == *it)) + if (!fmt.format_at_end(it) && (format_helper::l == *it)) { ++it; flags.set_length(format_flags::length::long_long_integer); @@ -1379,13 +1338,13 @@ public: { ++it; format_flags::length length = format_flags::length::size_type; - if (!format_helper::at_end(fmt, it)) + if (!fmt.format_at_end(it)) { if ((typename format_helper::char_type(format_helper::zero) + 3) == *it) { - typename format_helper::iterator tmp(it); + typename Format::iterator tmp(it); ++tmp; - if (!format_helper::at_end(fmt, tmp) && ((typename format_helper::char_type(format_helper::zero) + 2) == *tmp)) + if (!fmt.format_at_end(tmp) && ((typename format_helper::char_type(format_helper::zero) + 2) == *tmp)) { length = format_flags::length::integer_32; it = ++tmp; @@ -1393,9 +1352,9 @@ public: } else if ((typename format_helper::char_type(format_helper::zero) + 6) == *it) { - typename format_helper::iterator tmp(it); + typename Format::iterator tmp(it); ++tmp; - if (!format_helper::at_end(fmt, tmp) && ((typename format_helper::char_type(format_helper::zero) + 4) == *tmp)) + if (!fmt.format_at_end(tmp) && ((typename format_helper::char_type(format_helper::zero) + 4) == *tmp)) { length = format_flags::length::integer_64; it = ++tmp; @@ -1414,8 +1373,8 @@ public: } // Now we should find a conversion specifier - assert(!format_helper::at_end(fmt, it)); // missing conversion - if (format_helper::at_end(fmt, it)) return false; + assert(!fmt.format_at_end(it)); // missing conversion + if (fmt.format_at_end(it)) return false; switch (*it) { case format_helper::d: @@ -1498,14 +1457,14 @@ public: } private: - static bool have_dollar(Format const &fmt, typename format_helper::iterator const &it) + static bool have_dollar(Format const &fmt, typename Format::iterator const &it) { - return !format_helper::at_end(fmt, it) && (*it == format_helper::dollar); + return !fmt.format_at_end(it) && (*it == format_helper::dollar); } - static bool have_digit(Format const &fmt, typename format_helper::iterator const &it) + static bool have_digit(Format const &fmt, typename Format::iterator const &it) { - return !format_helper::at_end(fmt, it) && is_digit(*it); + return !fmt.format_at_end(it) && is_digit(*it); } static bool is_digit(typename format_helper::char_type value) @@ -1524,7 +1483,7 @@ private: num = (num * 10) + digit_value(digit); } - static int read_number(Format const &fmt, typename format_helper::iterator &it) + static int read_number(Format const &fmt, typename Format::iterator &it) { assert(have_digit(fmt, it)); int value = 0; @@ -1538,11 +1497,11 @@ private: // CORE FORMATTING FUNCTION //************************************************************************** -template -typename Stream::off_type stream_format(Stream &str, Format &&fmt, Params &&args) +template +typename Stream::off_type stream_format(Stream &str, Format const &args) { - typedef format_helper > > format_helper; - typedef typename format_helper::iterator iterator; + typedef format_helper > format_helper; + typedef typename Format::iterator iterator; class stream_preserver { public: @@ -1572,21 +1531,21 @@ typename Stream::off_type stream_format(Stream &str, Format &&fmt, Params &&args typename Stream::pos_type const begin(str.tellp()); stream_preserver const preserver(str); int next_pos(1); - iterator start = format_helper::begin(fmt); - for (iterator it = start; !format_helper::at_end(fmt, start); ) + iterator start = args.format_begin(); + for (iterator it = start; !args.format_at_end(start); ) { - while (!format_helper::at_end(fmt, it) && (format_helper::percent != *it)) ++it; + while (!args.format_at_end(it) && (format_helper::percent != *it)) ++it; if (start != it) { str.write(&*start, it - start); start = it; } - if (!format_helper::at_end(fmt, it)) + if (!args.format_at_end(it)) { // Try to parse a percent format specification format_flags flags; int arg_pos, width_pos, prec_pos; - if (!format_helper::parse_format(fmt, it, flags, next_pos, arg_pos, width_pos, prec_pos)) + if (!format_helper::parse_format(args, it, flags, next_pos, arg_pos, width_pos, prec_pos)) continue; // Handle parameterised width @@ -1594,8 +1553,8 @@ typename Stream::off_type stream_format(Stream &str, Format &&fmt, Params &&args { assert(flags.get_field_width() == 0U); assert(0 < width_pos); - assert(args.size() >= unsigned(width_pos)); - if ((0 < width_pos) && (args.size() >= unsigned(width_pos))) + assert(args.argument_count() >= unsigned(width_pos)); + if ((0 < width_pos) && (args.argument_count() >= unsigned(width_pos))) { int width; if (args[width_pos - 1].make_integer(width)) @@ -1622,8 +1581,8 @@ typename Stream::off_type stream_format(Stream &str, Format &&fmt, Params &&args { assert(flags.get_precision() < 0); assert(0 < prec_pos); - assert(args.size() >= unsigned(prec_pos)); - if ((0 < prec_pos) && (args.size() >= unsigned(prec_pos))) + assert(args.argument_count() >= unsigned(prec_pos)); + if ((0 < prec_pos) && (args.argument_count() >= unsigned(prec_pos))) { int precision; if (args[prec_pos - 1].make_integer(precision)) @@ -1648,8 +1607,8 @@ typename Stream::off_type stream_format(Stream &str, Format &&fmt, Params &&args else { assert(0 < arg_pos); - assert(args.size() >= unsigned(arg_pos)); - if ((0 >= arg_pos) || (args.size() < unsigned(arg_pos))) + assert(args.argument_count() >= unsigned(arg_pos)); + if ((0 >= arg_pos) || (args.argument_count() < unsigned(arg_pos))) continue; if (format_flags::conversion::tell == flags.get_conversion()) { @@ -1683,19 +1642,19 @@ typename Stream::off_type stream_format(Stream &str, Format &&fmt, Params &&args template inline typename Stream::off_type stream_format(Stream &str, Format const &fmt, Params &&... args) { - return detail::stream_format(str, fmt, detail::make_format_arguments(std::forward(args)...)); + return detail::stream_format(str, detail::make_format_argument_pack(fmt, std::forward(args)...)); } template inline typename Stream::off_type stream_format(Stream &str, detail::format_argument_pack const &args) { - return detail::stream_format(str, args, args); + return detail::stream_format(str, args); } template inline typename Stream::off_type stream_format(Stream &str, detail::format_argument_pack &&args) { - return detail::stream_format(str, args, args); + return detail::stream_format(str, args); }