Update changelog and disable internal
This commit is contained in:
parent
3135d95fd9
commit
98a7a8b405
@ -1,3 +1,69 @@
|
||||
7.0.0 - TBD
|
||||
|
||||
* Reduced the library size. For example, on macOS the stripped binary
|
||||
statically linked with {fmt} shrinked from ~368k to less than 100k:
|
||||
http://www.zverovich.net/2020/05/21/reducing-library-size.html
|
||||
|
||||
* Named arguments are now stored on stack (no dynamic memory allocations) and
|
||||
the generated binary code is more compact and efficient. For example
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("The answer is {answer}\n", fmt::arg("answer", 42));
|
||||
}
|
||||
|
||||
compiles to just (`godbolt <https://godbolt.org/z/NcfEp_>`__)
|
||||
|
||||
.. code:: asm
|
||||
|
||||
.LC0:
|
||||
.string "answer"
|
||||
.LC1:
|
||||
.string "The answer is {answer}\n"
|
||||
main:
|
||||
sub rsp, 56
|
||||
mov edi, OFFSET FLAT:.LC1
|
||||
mov esi, 23
|
||||
movabs rdx, 4611686018427387905
|
||||
lea rax, [rsp+32]
|
||||
lea rcx, [rsp+16]
|
||||
mov QWORD PTR [rsp+8], 1
|
||||
mov QWORD PTR [rsp], rax
|
||||
mov DWORD PTR [rsp+16], 42
|
||||
mov QWORD PTR [rsp+32], OFFSET FLAT:.LC0
|
||||
mov DWORD PTR [rsp+40], 0
|
||||
call fmt::v6::vprint(fmt::v6::basic_string_view<char>, fmt::v6::format_args)
|
||||
xor eax, eax
|
||||
add rsp, 56
|
||||
ret
|
||||
|
||||
.L.str.1:
|
||||
.asciz "answer"
|
||||
|
||||
* Implemented the ``'L'`` specifier for locale-specific formatting of
|
||||
floating-point numbers to improve compatibility with ``std::format``
|
||||
(`#1624 <https://github.com/fmtlib/fmt/issues/1624>`_).
|
||||
|
||||
* Improved documentation
|
||||
(`#1643 <https://github.com/fmtlib/fmt/pull/1643>`_).
|
||||
Thanks `@senior7515 (Alexander Gallego) <https://github.com/senior7515>`_,
|
||||
|
||||
* Fixed various warnings and compilation issues
|
||||
(`#1616 <https://github.com/fmtlib/fmt/pull/1616>`_,
|
||||
`#1622 <https://github.com/fmtlib/fmt/issues/1622>`_,
|
||||
`#1627 <https://github.com/fmtlib/fmt/pull/1627>`_,
|
||||
`#1628 <https://github.com/fmtlib/fmt/issues/1628>`_,
|
||||
`#1629 <https://github.com/fmtlib/fmt/pull/1629>`_
|
||||
`#1631 <https://github.com/fmtlib/fmt/issues/1631>`_,
|
||||
`#1633 <https://github.com/fmtlib/fmt/pull/1633>`_).
|
||||
Thanks `@gsjaardema (Greg Sjaardema) <https://github.com/gsjaardema>`_,
|
||||
`@gabime (Gabi Melman) <https://github.com/gabime>`_,
|
||||
`@johnor (Johan) <https://github.com/johnor>`_,
|
||||
`@gabime (Dmitry Kurkin) <https://github.com/Kurkin>`_.
|
||||
|
||||
6.2.1 - 2020-05-09
|
||||
------------------
|
||||
|
||||
|
@ -332,7 +332,9 @@ enum char8_type : unsigned char {};
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
#ifdef FMT_USE_INTERNAL
|
||||
namespace internal = detail; // DEPRECATED
|
||||
#endif
|
||||
|
||||
/**
|
||||
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
|
||||
@ -1592,7 +1594,7 @@ class dynamic_format_arg_store
|
||||
void clear() {
|
||||
data_.clear();
|
||||
named_info_.clear();
|
||||
dynamic_args_ = internal::dynamic_arg_list();
|
||||
dynamic_args_ = detail::dynamic_arg_list();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1373,7 +1373,7 @@ struct stringifier {
|
||||
}
|
||||
std::string operator()(basic_format_arg<format_context>::handle h) const {
|
||||
memory_buffer buf;
|
||||
internal::buffer<char>& base = buf;
|
||||
detail::buffer<char>& base = buf;
|
||||
format_parse_context parse_ctx({});
|
||||
format_context format_ctx(std::back_inserter(base), {}, {});
|
||||
h.format(parse_ctx, format_ctx);
|
||||
|
@ -39,7 +39,7 @@ class custom_arg_formatter
|
||||
|
||||
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::internal::buffer<char>& base = buffer;
|
||||
fmt::detail::buffer<char>& base = buffer;
|
||||
// Pass custom argument formatter as a template arg to vwrite.
|
||||
fmt::vformat_to<custom_arg_formatter>(std::back_inserter(base), format_str,
|
||||
args);
|
||||
|
108
test/format
108
test/format
@ -38,9 +38,9 @@ namespace std {
|
||||
|
||||
template<class Out, class charT> class basic_format_context;
|
||||
using format_context = basic_format_context<
|
||||
/* unspecified */ std::back_insert_iterator<fmt::internal::buffer<char>>, char>;
|
||||
/* unspecified */ std::back_insert_iterator<fmt::detail::buffer<char>>, char>;
|
||||
using wformat_context = basic_format_context<
|
||||
/* unspecified */ std::back_insert_iterator<fmt::internal::buffer<wchar_t>>, wchar_t>;
|
||||
/* unspecified */ std::back_insert_iterator<fmt::detail::buffer<wchar_t>>, wchar_t>;
|
||||
|
||||
template<class T, class charT = char> struct formatter {
|
||||
formatter() = delete;
|
||||
@ -219,7 +219,7 @@ namespace std {
|
||||
|
||||
// Implementation details:
|
||||
using format_arg = basic_format_arg<basic_format_context>;
|
||||
basic_format_context(Out out, basic_format_args<basic_format_context> args, fmt::internal::locale_ref)
|
||||
basic_format_context(Out out, basic_format_args<basic_format_context> args, fmt::detail::locale_ref)
|
||||
: args_(args), out_(out) {}
|
||||
detail::error_handler error_handler() const { return {}; }
|
||||
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
|
||||
@ -490,10 +490,10 @@ namespace detail {
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
class arg_formatter
|
||||
: public fmt::internal::arg_formatter_base<OutputIt, Char, error_handler> {
|
||||
: public fmt::detail::arg_formatter_base<OutputIt, Char, error_handler> {
|
||||
private:
|
||||
using char_type = Char;
|
||||
using base = fmt::internal::arg_formatter_base<OutputIt, Char, error_handler>;
|
||||
using base = fmt::detail::arg_formatter_base<OutputIt, Char, error_handler>;
|
||||
using format_context = std::basic_format_context<OutputIt, Char>;
|
||||
using parse_context = basic_format_parse_context<Char>;
|
||||
|
||||
@ -528,36 +528,36 @@ class arg_formatter
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
inline fmt::internal::type get_type(basic_format_arg<Context> arg) {
|
||||
inline fmt::detail::type get_type(basic_format_arg<Context> arg) {
|
||||
return visit_format_arg([&] (auto val) {
|
||||
using char_type = typename Context::char_type;
|
||||
using T = decltype(val);
|
||||
if (std::is_same_v<T, monostate>)
|
||||
return fmt::internal::type::none_type;
|
||||
return fmt::detail::type::none_type;
|
||||
if (std::is_same_v<T, bool>)
|
||||
return fmt::internal::type::bool_type;
|
||||
return fmt::detail::type::bool_type;
|
||||
if (std::is_same_v<T, char_type>)
|
||||
return fmt::internal::type::char_type;
|
||||
return fmt::detail::type::char_type;
|
||||
if (std::is_same_v<T, int>)
|
||||
return fmt::internal::type::int_type;
|
||||
return fmt::detail::type::int_type;
|
||||
if (std::is_same_v<T, unsigned int>)
|
||||
return fmt::internal::type::uint_type;
|
||||
return fmt::detail::type::uint_type;
|
||||
if (std::is_same_v<T, long long int>)
|
||||
return fmt::internal::type::long_long_type;
|
||||
return fmt::detail::type::long_long_type;
|
||||
if (std::is_same_v<T, unsigned long long int>)
|
||||
return fmt::internal::type::ulong_long_type;
|
||||
return fmt::detail::type::ulong_long_type;
|
||||
if (std::is_same_v<T, double>)
|
||||
return fmt::internal::type::double_type;
|
||||
return fmt::detail::type::double_type;
|
||||
if (std::is_same_v<T, long double>)
|
||||
return fmt::internal::type::long_double_type;
|
||||
return fmt::detail::type::long_double_type;
|
||||
if (std::is_same_v<T, const char_type*>)
|
||||
return fmt::internal::type::cstring_type;
|
||||
return fmt::detail::type::cstring_type;
|
||||
if (std::is_same_v<T, basic_string_view<char_type>>)
|
||||
return fmt::internal::type::string_type;
|
||||
return fmt::detail::type::string_type;
|
||||
if (std::is_same_v<T, const void*>)
|
||||
return fmt::internal::type::pointer_type;
|
||||
return fmt::detail::type::pointer_type;
|
||||
assert(get_value(arg).index() == 12);
|
||||
return fmt::internal::type::custom_type;
|
||||
return fmt::detail::type::custom_type;
|
||||
}, arg);
|
||||
}
|
||||
|
||||
@ -585,13 +585,13 @@ struct format_handler : detail::error_handler {
|
||||
|
||||
format_handler(iterator out, basic_string_view<Char> str,
|
||||
basic_format_args<Context> format_args,
|
||||
fmt::internal::locale_ref loc)
|
||||
fmt::detail::locale_ref loc)
|
||||
: parse_ctx(str), context(out, format_args, loc) {}
|
||||
|
||||
void on_text(const Char* begin, const Char* end) {
|
||||
auto size = fmt::internal::to_unsigned(end - begin);
|
||||
auto size = fmt::detail::to_unsigned(end - begin);
|
||||
auto out = context.out();
|
||||
auto&& it = fmt::internal::reserve(out, size);
|
||||
auto&& it = fmt::detail::reserve(out, size);
|
||||
it = std::copy_n(begin, size, it);
|
||||
context.advance_to(out);
|
||||
}
|
||||
@ -614,9 +614,9 @@ struct format_handler : detail::error_handler {
|
||||
custom_formatter<Context> f(parse_ctx, context);
|
||||
if (visit_format_arg(f, arg)) return &*parse_ctx.begin();
|
||||
fmt::basic_format_specs<Char> specs;
|
||||
using fmt::internal::specs_handler;
|
||||
using fmt::detail::specs_handler;
|
||||
using parse_context = basic_format_parse_context<Char>;
|
||||
fmt::internal::specs_checker<specs_handler<parse_context, Context>> handler(
|
||||
fmt::detail::specs_checker<specs_handler<parse_context, Context>> handler(
|
||||
specs_handler<parse_context, Context>(specs, parse_ctx, context), get_type(arg));
|
||||
begin = parse_format_specs(begin, end, handler);
|
||||
if (begin == end || *begin != '}') on_error("missing '}' in format string");
|
||||
@ -635,45 +635,45 @@ struct formatter {
|
||||
// terminating '}'.
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext& ctx) {
|
||||
namespace internal = fmt::internal;
|
||||
typedef internal::dynamic_specs_handler<ParseContext> handler_type;
|
||||
auto type = internal::mapped_type_constant<T, fmt::buffer_context<Char>>::value;
|
||||
internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
|
||||
namespace detail = fmt::detail;
|
||||
typedef detail::dynamic_specs_handler<ParseContext> handler_type;
|
||||
auto type = detail::mapped_type_constant<T, fmt::buffer_context<Char>>::value;
|
||||
detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
|
||||
type);
|
||||
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
|
||||
auto type_spec = specs_.type;
|
||||
auto eh = ctx.error_handler();
|
||||
switch (type) {
|
||||
case internal::type::none_type:
|
||||
case detail::type::none_type:
|
||||
FMT_ASSERT(false, "invalid argument type");
|
||||
break;
|
||||
case internal::type::int_type:
|
||||
case internal::type::uint_type:
|
||||
case internal::type::long_long_type:
|
||||
case internal::type::ulong_long_type:
|
||||
case internal::type::bool_type:
|
||||
case detail::type::int_type:
|
||||
case detail::type::uint_type:
|
||||
case detail::type::long_long_type:
|
||||
case detail::type::ulong_long_type:
|
||||
case detail::type::bool_type:
|
||||
handle_int_type_spec(type_spec,
|
||||
internal::int_type_checker<decltype(eh)>(eh));
|
||||
detail::int_type_checker<decltype(eh)>(eh));
|
||||
break;
|
||||
case internal::type::char_type:
|
||||
case detail::type::char_type:
|
||||
handle_char_specs(
|
||||
&specs_, internal::char_specs_checker<decltype(eh)>(type_spec, eh));
|
||||
&specs_, detail::char_specs_checker<decltype(eh)>(type_spec, eh));
|
||||
break;
|
||||
case internal::type::double_type:
|
||||
case internal::type::long_double_type:
|
||||
internal::parse_float_type_spec(specs_, eh);
|
||||
case detail::type::double_type:
|
||||
case detail::type::long_double_type:
|
||||
detail::parse_float_type_spec(specs_, eh);
|
||||
break;
|
||||
case internal::type::cstring_type:
|
||||
internal::handle_cstring_type_spec(
|
||||
type_spec, internal::cstring_type_checker<decltype(eh)>(eh));
|
||||
case detail::type::cstring_type:
|
||||
detail::handle_cstring_type_spec(
|
||||
type_spec, detail::cstring_type_checker<decltype(eh)>(eh));
|
||||
break;
|
||||
case internal::type::string_type:
|
||||
internal::check_string_type_spec(type_spec, eh);
|
||||
case detail::type::string_type:
|
||||
detail::check_string_type_spec(type_spec, eh);
|
||||
break;
|
||||
case internal::type::pointer_type:
|
||||
internal::check_pointer_type_spec(type_spec, eh);
|
||||
case detail::type::pointer_type:
|
||||
detail::check_pointer_type_spec(type_spec, eh);
|
||||
break;
|
||||
case internal::type::custom_type:
|
||||
case detail::type::custom_type:
|
||||
// Custom format specifiers should be checked in parse functions of
|
||||
// formatter specializations.
|
||||
break;
|
||||
@ -683,9 +683,9 @@ struct formatter {
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
fmt::internal::handle_dynamic_spec<fmt::internal::width_checker>(
|
||||
fmt::detail::handle_dynamic_spec<fmt::detail::width_checker>(
|
||||
specs_.width, specs_.width_ref, ctx);
|
||||
fmt::internal::handle_dynamic_spec<fmt::internal::precision_checker>(
|
||||
fmt::detail::handle_dynamic_spec<fmt::detail::precision_checker>(
|
||||
specs_.precision, specs_.precision_ref, ctx);
|
||||
using af = arg_formatter<typename FormatContext::iterator,
|
||||
typename FormatContext::char_type>;
|
||||
@ -694,7 +694,7 @@ struct formatter {
|
||||
}
|
||||
|
||||
private:
|
||||
fmt::internal::dynamic_format_specs<Char> specs_;
|
||||
fmt::detail::dynamic_format_specs<Char> specs_;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
@ -711,11 +711,11 @@ template<class... Args>
|
||||
|
||||
string vformat(string_view fmt, format_args args) {
|
||||
fmt::memory_buffer mbuf;
|
||||
fmt::internal::buffer<char>& buf = mbuf;
|
||||
fmt::detail::buffer<char>& buf = mbuf;
|
||||
using af = detail::arg_formatter<fmt::format_context::iterator, char>;
|
||||
detail::format_handler<af, char, format_context>
|
||||
h(std::back_inserter(buf), fmt, args, {});
|
||||
fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||
fmt::detail::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||
return to_string(mbuf);
|
||||
}
|
||||
|
||||
@ -738,7 +738,7 @@ template<class Out>
|
||||
using af = detail::arg_formatter<Out, char>;
|
||||
detail::format_handler<af, char, basic_format_context<Out, char>>
|
||||
h(out, fmt, args, {});
|
||||
fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||
fmt::detail::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||
return h.context.out();
|
||||
}
|
||||
|
||||
|
@ -1846,7 +1846,7 @@ class mock_arg_formatter
|
||||
|
||||
static void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::internal::buffer<char>& base = buffer;
|
||||
fmt::detail::buffer<char>& base = buffer;
|
||||
fmt::vformat_to<mock_arg_formatter>(std::back_inserter(base), format_str,
|
||||
args);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user