mirror of
https://github.com/fmtlib/fmt.git
synced 2025-06-25 09:21:41 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
5f7f7b954d | |||
5d3f0741e3 | |||
563cbb6c21 | |||
425778aa67 | |||
69a84198b0 | |||
5c04504932 | |||
556a1cfb34 | |||
28a8eae850 | |||
236fea1f00 |
@ -1,3 +1,27 @@
|
||||
7.1.1 - 2020-11-01
|
||||
------------------
|
||||
|
||||
* Fixed ABI compatibility with 7.0.x
|
||||
(`#1961 <https://github.com/fmtlib/fmt/issues/1961>`_).
|
||||
|
||||
* Added the ``FMT_ARM_ABI_COMPATIBILITY`` macro to work around ABI
|
||||
incompatibility between GCC and Clang on ARM
|
||||
(`#1919 <https://github.com/fmtlib/fmt/issues/1919>`_).
|
||||
|
||||
* Worked around a SFINAE bug in GCC 8
|
||||
(`#1957 <https://github.com/fmtlib/fmt/issues/1957>`_).
|
||||
|
||||
* Fixed linkage errors when building with GCC's LTO
|
||||
(`#1955 <https://github.com/fmtlib/fmt/issues/1955>`_).
|
||||
|
||||
* Fixed a compilation error when building without ``__builtin_clz`` or equivalent
|
||||
(`#1968 <https://github.com/fmtlib/fmt/pull/1968>`_).
|
||||
Thanks `@tohammer (Tobias Hammer) <https://github.com/tohammer>`_.
|
||||
|
||||
* Fixed a sign conversion warning
|
||||
(`#1964 <https://github.com/fmtlib/fmt/pull/1964>`_).
|
||||
Thanks `@OptoCloud <https://github.com/OptoCloud>`_.
|
||||
|
||||
7.1.0 - 2020-10-25
|
||||
------------------
|
||||
|
||||
|
@ -6,7 +6,7 @@ import errno, os, shutil, sys, tempfile
|
||||
from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0', '5.1.0', '5.2.0', '5.2.1', '5.3.0', '6.0.0', '6.1.0', '6.1.1', '6.1.2', '6.2.0', '6.2.1', '7.0.0', '7.0.1', '7.0.2', '7.0.3', '7.1.0']
|
||||
versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0', '5.1.0', '5.2.0', '5.2.1', '5.3.0', '6.0.0', '6.1.0', '6.1.1', '6.1.2', '6.2.0', '6.2.1', '7.0.0', '7.0.1', '7.0.2', '7.0.3', '7.1.0', '7.1.1']
|
||||
|
||||
def pip_install(package, commit=None, **kwargs):
|
||||
"Install package using pip."
|
||||
|
@ -589,10 +589,11 @@ OutputIt vformat_to(
|
||||
\endrst
|
||||
*/
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char_t<S>>::value&&
|
||||
detail::is_string<S>::value)>
|
||||
inline OutputIt format_to(OutputIt out, const text_style& ts,
|
||||
const S& format_str, Args&&... args) {
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value&&
|
||||
detail::is_string<S>::value>
|
||||
inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
|
||||
Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
return vformat_to(out, ts, to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
@ -667,14 +667,15 @@ OutputIt format_to(OutputIt out, const S&, const Args&... args) {
|
||||
return format_to(out, compiled, args...);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<
|
||||
OutputIt, typename CompiledFormat::char_type>::value&&
|
||||
std::is_base_of<detail::basic_compiled_format,
|
||||
CompiledFormat>::value)>
|
||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||
const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args>
|
||||
auto format_to_n(OutputIt out, size_t n, const CompiledFormat& cf,
|
||||
const Args&... args) ->
|
||||
typename std::enable_if<
|
||||
detail::is_output_iterator<OutputIt,
|
||||
typename CompiledFormat::char_type>::value &&
|
||||
std::is_base_of<detail::basic_compiled_format,
|
||||
CompiledFormat>::value,
|
||||
format_to_n_result<OutputIt>>::type {
|
||||
auto it =
|
||||
format_to(detail::truncating_iterator<OutputIt>(out, n), cf, args...);
|
||||
return {it.base(), it.count()};
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||
#define FMT_VERSION 70100
|
||||
#define FMT_VERSION 70101
|
||||
|
||||
#ifdef __clang__
|
||||
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
||||
@ -1929,7 +1929,14 @@ template <typename Context> class basic_format_args {
|
||||
}
|
||||
};
|
||||
|
||||
/** An alias to ``basic_format_args<context>``. */
|
||||
#ifdef FMT_ARM_ABI_COMPATIBILITY
|
||||
/** An alias to ``basic_format_args<format_context>``. */
|
||||
// Separate types would result in shorter symbols but break ABI compatibility
|
||||
// between clang and gcc on ARM (#1919).
|
||||
using format_args = basic_format_args<format_context>;
|
||||
using wformat_args = basic_format_args<wformat_context>;
|
||||
#else
|
||||
// DEPRECATED! These are kept for ABI compatibility.
|
||||
// It is a separate type rather than an alias to make symbols readable.
|
||||
struct format_args : basic_format_args<format_context> {
|
||||
template <typename... Args>
|
||||
@ -1938,6 +1945,7 @@ struct format_args : basic_format_args<format_context> {
|
||||
struct wformat_args : basic_format_args<wformat_context> {
|
||||
using basic_format_args::basic_format_args;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
@ -1968,10 +1976,10 @@ inline void vprint_mojibake(std::FILE*, string_view, format_args) {}
|
||||
// GCC 8 and earlier cannot handle std::back_insert_iterator<Container> with
|
||||
// vformat_to<ArgFormatter>(...) overload, so SFINAE on iterator type instead.
|
||||
template <typename OutputIt, typename S, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||
OutputIt vformat_to(
|
||||
OutputIt out, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
bool enable = detail::is_output_iterator<OutputIt, Char>::value>
|
||||
auto vformat_to(OutputIt out, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> typename std::enable_if<enable, OutputIt>::type {
|
||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
||||
detail::vformat_to(buf, to_string_view(format_str), args);
|
||||
return detail::get_iterator(buf);
|
||||
@ -2023,10 +2031,10 @@ inline format_to_n_result<OutputIt> vformat_to_n(
|
||||
\endrst
|
||||
*/
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char_t<S>>::value)>
|
||||
inline format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||
const S& format_str,
|
||||
const Args&... args) {
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
|
||||
inline auto format_to_n(OutputIt out, size_t n, const S& format_str,
|
||||
const Args&... args) ->
|
||||
typename std::enable_if<enable, format_to_n_result<OutputIt>>::type {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat_to_n(out, n, to_string_view(format_str), vargs);
|
||||
}
|
||||
|
@ -261,11 +261,19 @@ const uint64_t basic_data<T>::powers_of_10_64[] = {
|
||||
10000000000000000000ULL};
|
||||
|
||||
template <typename T>
|
||||
const uint32_t basic_data<T>::zero_or_powers_of_10_32[] = {0, 0,
|
||||
const uint32_t basic_data<T>::zero_or_powers_of_10_32[] = {0,
|
||||
FMT_POWERS_OF_10(1)};
|
||||
|
||||
template <typename T>
|
||||
const uint64_t basic_data<T>::zero_or_powers_of_10_64[] = {
|
||||
0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1000000000ULL),
|
||||
10000000000000000000ULL};
|
||||
|
||||
template <typename T>
|
||||
const uint32_t basic_data<T>::zero_or_powers_of_10_32_new[] = {
|
||||
0, 0, FMT_POWERS_OF_10(1)};
|
||||
|
||||
template <typename T>
|
||||
const uint64_t basic_data<T>::zero_or_powers_of_10_64_new[] = {
|
||||
0, 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1000000000ULL),
|
||||
10000000000000000000ULL};
|
||||
|
||||
@ -1756,7 +1764,7 @@ inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT {
|
||||
#ifdef FMT_BUILTIN_CTZLL
|
||||
return FMT_BUILTIN_CTZLL(x) >= exp;
|
||||
#else
|
||||
return exp < num_bits<uint64_t>()) && x == ((x >> exp) << exp);
|
||||
return exp < num_bits<uint64_t>() && x == ((x >> exp) << exp);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1901,7 +1909,7 @@ template <> struct cache_accessor<double> {
|
||||
uint64_t pow5 = data::powers_of_5_64[offset];
|
||||
uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5);
|
||||
uint128_wrapper middle_low =
|
||||
umul128(base_cache.low() - (kb < 0 ? 1 : 0), pow5);
|
||||
umul128(base_cache.low() - (kb < 0 ? 1u : 0u), pow5);
|
||||
|
||||
recovered_cache += middle_low.high();
|
||||
|
||||
|
@ -866,8 +866,8 @@ template <typename T> struct FMT_EXTERN_TEMPLATE_API divtest_table_entry {
|
||||
// Static data is placed in this class template for the header-only config.
|
||||
template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
|
||||
static const uint64_t powers_of_10_64[];
|
||||
static const uint32_t zero_or_powers_of_10_32[];
|
||||
static const uint64_t zero_or_powers_of_10_64[];
|
||||
static const uint32_t zero_or_powers_of_10_32_new[];
|
||||
static const uint64_t zero_or_powers_of_10_64_new[];
|
||||
static const uint64_t grisu_pow10_significands[];
|
||||
static const int16_t grisu_pow10_exponents[];
|
||||
static const divtest_table_entry<uint32_t> divtest_table_for_pow5_32[];
|
||||
@ -891,6 +891,10 @@ template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
|
||||
static const char signs[];
|
||||
static const char left_padding_shifts[5];
|
||||
static const char right_padding_shifts[5];
|
||||
|
||||
// DEPRECATED! These are for ABI compatibility.
|
||||
static const uint32_t zero_or_powers_of_10_32[];
|
||||
static const uint64_t zero_or_powers_of_10_64[];
|
||||
};
|
||||
|
||||
// Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
|
||||
@ -917,7 +921,7 @@ struct data : basic_data<> {};
|
||||
inline int count_digits(uint64_t n) {
|
||||
// https://github.com/fmtlib/format-benchmark/blob/master/digits10
|
||||
auto t = bsr2log10(FMT_BUILTIN_CLZLL(n | 1) ^ 63);
|
||||
return t - (n < data::zero_or_powers_of_10_64[t]);
|
||||
return t - (n < data::zero_or_powers_of_10_64_new[t]);
|
||||
}
|
||||
#else
|
||||
// Fallback version of count_digits used when __builtin_clz is not available.
|
||||
@ -984,7 +988,7 @@ template <> int count_digits<4>(detail::fallback_uintptr n);
|
||||
// Optional version of count_digits for better performance on 32-bit platforms.
|
||||
inline int count_digits(uint32_t n) {
|
||||
auto t = bsr2log10(FMT_BUILTIN_CLZ(n | 1) ^ 31);
|
||||
return t - (n < data::zero_or_powers_of_10_32[t]);
|
||||
return t - (n < data::zero_or_powers_of_10_32_new[t]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3056,8 +3060,7 @@ struct format_handler : detail::error_handler {
|
||||
basic_format_parse_context<Char> parse_context;
|
||||
Context context;
|
||||
|
||||
format_handler(OutputIt out,
|
||||
basic_string_view<Char> str,
|
||||
format_handler(OutputIt out, basic_string_view<Char> str,
|
||||
basic_format_args<Context> format_args, detail::locale_ref loc)
|
||||
: parse_context(str), context(out, format_args, loc) {}
|
||||
|
||||
@ -3080,8 +3083,8 @@ struct format_handler : detail::error_handler {
|
||||
FMT_INLINE void on_replacement_field(int id, const Char*) {
|
||||
auto arg = get_arg(context, id);
|
||||
context.advance_to(visit_format_arg(
|
||||
default_arg_formatter<OutputIt, Char>{
|
||||
context.out(), context.args(), context.locale()},
|
||||
default_arg_formatter<OutputIt, Char>{context.out(), context.args(),
|
||||
context.locale()},
|
||||
arg));
|
||||
}
|
||||
|
||||
@ -3105,8 +3108,8 @@ struct format_handler : detail::error_handler {
|
||||
if (begin == end || *begin != '}')
|
||||
on_error("missing '}' in format string");
|
||||
}
|
||||
context.advance_to(
|
||||
visit_format_arg(arg_formatter<OutputIt, Char>(context, &parse_context, &specs), arg));
|
||||
context.advance_to(visit_format_arg(
|
||||
arg_formatter<OutputIt, Char>(context, &parse_context, &specs), arg));
|
||||
return begin;
|
||||
}
|
||||
};
|
||||
@ -3776,8 +3779,8 @@ void detail::vformat_to(
|
||||
arg);
|
||||
return;
|
||||
}
|
||||
format_handler<iterator, Char, buffer_context<Char>> h(
|
||||
out, format_str, args, loc);
|
||||
format_handler<iterator, Char, buffer_context<Char>> h(out, format_str, args,
|
||||
loc);
|
||||
parse_format_string<false>(format_str, h);
|
||||
}
|
||||
|
||||
@ -3786,6 +3789,7 @@ extern template void detail::vformat_to(detail::buffer<char>&, string_view,
|
||||
basic_format_args<format_context>,
|
||||
detail::locale_ref);
|
||||
namespace detail {
|
||||
|
||||
extern template FMT_API std::string grouping_impl<char>(locale_ref loc);
|
||||
extern template FMT_API std::string grouping_impl<wchar_t>(locale_ref loc);
|
||||
extern template FMT_API char thousands_sep_impl<char>(locale_ref loc);
|
||||
|
@ -51,10 +51,10 @@ inline OutputIt vformat_to(
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
||||
const S& format_str, Args&&... args) {
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
|
||||
inline auto format_to(OutputIt out, const std::locale& loc,
|
||||
const S& format_str, Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat_to(out, loc, to_string_view(format_str), vargs);
|
||||
}
|
||||
|
@ -23,6 +23,36 @@ int format_float(char* buf, std::size_t size, const char* format, int precision,
|
||||
return precision < 0 ? snprintf_ptr(buf, size, format, value)
|
||||
: snprintf_ptr(buf, size, format, precision, value);
|
||||
}
|
||||
|
||||
template dragonbox::decimal_fp<float> dragonbox::to_decimal(float x)
|
||||
FMT_NOEXCEPT;
|
||||
template dragonbox::decimal_fp<double> dragonbox::to_decimal(double x)
|
||||
FMT_NOEXCEPT;
|
||||
|
||||
// DEPRECATED! This function exists for ABI compatibility.
|
||||
template <typename Char>
|
||||
typename basic_format_context<std::back_insert_iterator<buffer<Char>>,
|
||||
Char>::iterator
|
||||
vformat_to(buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||
basic_format_args<basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
|
||||
type_identity_t<Char>>>
|
||||
args) {
|
||||
using iterator = std::back_insert_iterator<buffer<char>>;
|
||||
using context = basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
|
||||
type_identity_t<Char>>;
|
||||
auto out = iterator(buf);
|
||||
format_handler<iterator, Char, context> h(out, format_str, args, {});
|
||||
parse_format_string<false>(format_str, h);
|
||||
return out;
|
||||
}
|
||||
template basic_format_context<std::back_insert_iterator<buffer<char>>,
|
||||
char>::iterator
|
||||
vformat_to(buffer<char>&, string_view,
|
||||
basic_format_args<basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<char>>>,
|
||||
type_identity_t<char>>>);
|
||||
} // namespace detail
|
||||
|
||||
template struct FMT_INSTANTIATION_DEF_API detail::basic_data<void>;
|
||||
|
Reference in New Issue
Block a user