mirror of
https://github.com/fmtlib/fmt.git
synced 2025-02-05 00:40:12 +00:00
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
|
6.2.1 - 2020-05-09
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -332,7 +332,9 @@ enum char8_type : unsigned char {};
|
|||||||
#endif
|
#endif
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
#ifdef FMT_USE_INTERNAL
|
||||||
namespace internal = detail; // DEPRECATED
|
namespace internal = detail; // DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
|
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() {
|
void clear() {
|
||||||
data_.clear();
|
data_.clear();
|
||||||
named_info_.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 {
|
std::string operator()(basic_format_arg<format_context>::handle h) const {
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
internal::buffer<char>& base = buf;
|
detail::buffer<char>& base = buf;
|
||||||
format_parse_context parse_ctx({});
|
format_parse_context parse_ctx({});
|
||||||
format_context format_ctx(std::back_inserter(base), {}, {});
|
format_context format_ctx(std::back_inserter(base), {}, {});
|
||||||
h.format(parse_ctx, format_ctx);
|
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) {
|
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||||
fmt::memory_buffer buffer;
|
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.
|
// Pass custom argument formatter as a template arg to vwrite.
|
||||||
fmt::vformat_to<custom_arg_formatter>(std::back_inserter(base), format_str,
|
fmt::vformat_to<custom_arg_formatter>(std::back_inserter(base), format_str,
|
||||||
args);
|
args);
|
||||||
|
108
test/format
108
test/format
@ -38,9 +38,9 @@ namespace std {
|
|||||||
|
|
||||||
template<class Out, class charT> class basic_format_context;
|
template<class Out, class charT> class basic_format_context;
|
||||||
using format_context = 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<
|
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 {
|
template<class T, class charT = char> struct formatter {
|
||||||
formatter() = delete;
|
formatter() = delete;
|
||||||
@ -219,7 +219,7 @@ namespace std {
|
|||||||
|
|
||||||
// Implementation details:
|
// Implementation details:
|
||||||
using format_arg = basic_format_arg<basic_format_context>;
|
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) {}
|
: args_(args), out_(out) {}
|
||||||
detail::error_handler error_handler() const { return {}; }
|
detail::error_handler error_handler() const { return {}; }
|
||||||
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
|
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
|
||||||
@ -490,10 +490,10 @@ namespace detail {
|
|||||||
|
|
||||||
template <typename OutputIt, typename Char>
|
template <typename OutputIt, typename Char>
|
||||||
class arg_formatter
|
class arg_formatter
|
||||||
: public fmt::internal::arg_formatter_base<OutputIt, Char, error_handler> {
|
: public fmt::detail::arg_formatter_base<OutputIt, Char, error_handler> {
|
||||||
private:
|
private:
|
||||||
using char_type = Char;
|
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 format_context = std::basic_format_context<OutputIt, Char>;
|
||||||
using parse_context = basic_format_parse_context<Char>;
|
using parse_context = basic_format_parse_context<Char>;
|
||||||
|
|
||||||
@ -528,36 +528,36 @@ class arg_formatter
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context>
|
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) {
|
return visit_format_arg([&] (auto val) {
|
||||||
using char_type = typename Context::char_type;
|
using char_type = typename Context::char_type;
|
||||||
using T = decltype(val);
|
using T = decltype(val);
|
||||||
if (std::is_same_v<T, monostate>)
|
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>)
|
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>)
|
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>)
|
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>)
|
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>)
|
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>)
|
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>)
|
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>)
|
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*>)
|
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>>)
|
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*>)
|
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);
|
assert(get_value(arg).index() == 12);
|
||||||
return fmt::internal::type::custom_type;
|
return fmt::detail::type::custom_type;
|
||||||
}, arg);
|
}, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,13 +585,13 @@ struct format_handler : detail::error_handler {
|
|||||||
|
|
||||||
format_handler(iterator out, basic_string_view<Char> str,
|
format_handler(iterator out, basic_string_view<Char> str,
|
||||||
basic_format_args<Context> format_args,
|
basic_format_args<Context> format_args,
|
||||||
fmt::internal::locale_ref loc)
|
fmt::detail::locale_ref loc)
|
||||||
: parse_ctx(str), context(out, format_args, loc) {}
|
: parse_ctx(str), context(out, format_args, loc) {}
|
||||||
|
|
||||||
void on_text(const Char* begin, const Char* end) {
|
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 out = context.out();
|
||||||
auto&& it = fmt::internal::reserve(out, size);
|
auto&& it = fmt::detail::reserve(out, size);
|
||||||
it = std::copy_n(begin, size, it);
|
it = std::copy_n(begin, size, it);
|
||||||
context.advance_to(out);
|
context.advance_to(out);
|
||||||
}
|
}
|
||||||
@ -614,9 +614,9 @@ struct format_handler : detail::error_handler {
|
|||||||
custom_formatter<Context> f(parse_ctx, context);
|
custom_formatter<Context> f(parse_ctx, context);
|
||||||
if (visit_format_arg(f, arg)) return &*parse_ctx.begin();
|
if (visit_format_arg(f, arg)) return &*parse_ctx.begin();
|
||||||
fmt::basic_format_specs<Char> specs;
|
fmt::basic_format_specs<Char> specs;
|
||||||
using fmt::internal::specs_handler;
|
using fmt::detail::specs_handler;
|
||||||
using parse_context = basic_format_parse_context<Char>;
|
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));
|
specs_handler<parse_context, Context>(specs, parse_ctx, context), get_type(arg));
|
||||||
begin = parse_format_specs(begin, end, handler);
|
begin = parse_format_specs(begin, end, handler);
|
||||||
if (begin == end || *begin != '}') on_error("missing '}' in format string");
|
if (begin == end || *begin != '}') on_error("missing '}' in format string");
|
||||||
@ -635,45 +635,45 @@ struct formatter {
|
|||||||
// terminating '}'.
|
// terminating '}'.
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext& ctx) {
|
FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext& ctx) {
|
||||||
namespace internal = fmt::internal;
|
namespace detail = fmt::detail;
|
||||||
typedef internal::dynamic_specs_handler<ParseContext> handler_type;
|
typedef detail::dynamic_specs_handler<ParseContext> handler_type;
|
||||||
auto type = internal::mapped_type_constant<T, fmt::buffer_context<Char>>::value;
|
auto type = detail::mapped_type_constant<T, fmt::buffer_context<Char>>::value;
|
||||||
internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
|
detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
|
||||||
type);
|
type);
|
||||||
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
|
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
|
||||||
auto type_spec = specs_.type;
|
auto type_spec = specs_.type;
|
||||||
auto eh = ctx.error_handler();
|
auto eh = ctx.error_handler();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case internal::type::none_type:
|
case detail::type::none_type:
|
||||||
FMT_ASSERT(false, "invalid argument type");
|
FMT_ASSERT(false, "invalid argument type");
|
||||||
break;
|
break;
|
||||||
case internal::type::int_type:
|
case detail::type::int_type:
|
||||||
case internal::type::uint_type:
|
case detail::type::uint_type:
|
||||||
case internal::type::long_long_type:
|
case detail::type::long_long_type:
|
||||||
case internal::type::ulong_long_type:
|
case detail::type::ulong_long_type:
|
||||||
case internal::type::bool_type:
|
case detail::type::bool_type:
|
||||||
handle_int_type_spec(type_spec,
|
handle_int_type_spec(type_spec,
|
||||||
internal::int_type_checker<decltype(eh)>(eh));
|
detail::int_type_checker<decltype(eh)>(eh));
|
||||||
break;
|
break;
|
||||||
case internal::type::char_type:
|
case detail::type::char_type:
|
||||||
handle_char_specs(
|
handle_char_specs(
|
||||||
&specs_, internal::char_specs_checker<decltype(eh)>(type_spec, eh));
|
&specs_, detail::char_specs_checker<decltype(eh)>(type_spec, eh));
|
||||||
break;
|
break;
|
||||||
case internal::type::double_type:
|
case detail::type::double_type:
|
||||||
case internal::type::long_double_type:
|
case detail::type::long_double_type:
|
||||||
internal::parse_float_type_spec(specs_, eh);
|
detail::parse_float_type_spec(specs_, eh);
|
||||||
break;
|
break;
|
||||||
case internal::type::cstring_type:
|
case detail::type::cstring_type:
|
||||||
internal::handle_cstring_type_spec(
|
detail::handle_cstring_type_spec(
|
||||||
type_spec, internal::cstring_type_checker<decltype(eh)>(eh));
|
type_spec, detail::cstring_type_checker<decltype(eh)>(eh));
|
||||||
break;
|
break;
|
||||||
case internal::type::string_type:
|
case detail::type::string_type:
|
||||||
internal::check_string_type_spec(type_spec, eh);
|
detail::check_string_type_spec(type_spec, eh);
|
||||||
break;
|
break;
|
||||||
case internal::type::pointer_type:
|
case detail::type::pointer_type:
|
||||||
internal::check_pointer_type_spec(type_spec, eh);
|
detail::check_pointer_type_spec(type_spec, eh);
|
||||||
break;
|
break;
|
||||||
case internal::type::custom_type:
|
case detail::type::custom_type:
|
||||||
// Custom format specifiers should be checked in parse functions of
|
// Custom format specifiers should be checked in parse functions of
|
||||||
// formatter specializations.
|
// formatter specializations.
|
||||||
break;
|
break;
|
||||||
@ -683,9 +683,9 @@ struct formatter {
|
|||||||
|
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
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);
|
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);
|
specs_.precision, specs_.precision_ref, ctx);
|
||||||
using af = arg_formatter<typename FormatContext::iterator,
|
using af = arg_formatter<typename FormatContext::iterator,
|
||||||
typename FormatContext::char_type>;
|
typename FormatContext::char_type>;
|
||||||
@ -694,7 +694,7 @@ struct formatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
fmt::internal::dynamic_format_specs<Char> specs_;
|
fmt::detail::dynamic_format_specs<Char> specs_;
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
@ -711,11 +711,11 @@ template<class... Args>
|
|||||||
|
|
||||||
string vformat(string_view fmt, format_args args) {
|
string vformat(string_view fmt, format_args args) {
|
||||||
fmt::memory_buffer mbuf;
|
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>;
|
using af = detail::arg_formatter<fmt::format_context::iterator, char>;
|
||||||
detail::format_handler<af, char, format_context>
|
detail::format_handler<af, char, format_context>
|
||||||
h(std::back_inserter(buf), fmt, args, {});
|
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);
|
return to_string(mbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -738,7 +738,7 @@ template<class Out>
|
|||||||
using af = detail::arg_formatter<Out, char>;
|
using af = detail::arg_formatter<Out, char>;
|
||||||
detail::format_handler<af, char, basic_format_context<Out, char>>
|
detail::format_handler<af, char, basic_format_context<Out, char>>
|
||||||
h(out, fmt, args, {});
|
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();
|
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) {
|
static void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||||
fmt::memory_buffer buffer;
|
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,
|
fmt::vformat_to<mock_arg_formatter>(std::back_inserter(base), format_str,
|
||||||
args);
|
args);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user