mirror of
https://github.com/fmtlib/fmt.git
synced 2025-12-22 23:13:30 +01:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd4af11efc | ||
|
|
1ebc2f7cc6 | ||
|
|
f4c997062a | ||
|
|
72920ba30a | ||
|
|
0907c08ae5 | ||
|
|
37c8f4eaf3 | ||
|
|
eaaaec9992 | ||
|
|
ccf8561cb3 | ||
|
|
0cc73ebf79 | ||
|
|
33efc3c94f | ||
|
|
b9d749095e | ||
|
|
86b63bb71a | ||
|
|
cbf6be9604 | ||
|
|
229ee9b469 | ||
|
|
2b7a146fa1 | ||
|
|
89d0c7124b | ||
|
|
f19b1a521e | ||
|
|
5c67fefb26 | ||
|
|
1d2a556e1b | ||
|
|
04c9b62fb4 | ||
|
|
6be6762e57 | ||
|
|
f1dd2eb3c0 | ||
|
|
fbf3b943cc | ||
|
|
a29a01d304 | ||
|
|
9f0b3afb79 | ||
|
|
86b2f99f8c | ||
|
|
c472ff12d8 |
@@ -24,15 +24,23 @@ function(join result_var)
|
||||
set(${result_var} "${result}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Sets a cache variable with a docstring joined from multiple arguments:
|
||||
# set(<variable> <value>... CACHE <type> <docstring>...)
|
||||
# This allows splitting a long docstring for readability.
|
||||
function(set_verbose)
|
||||
cmake_parse_arguments(SET_VERBOSE "" "" "CACHE" ${ARGN})
|
||||
list(GET SET_VERBOSE_CACHE 0 type)
|
||||
list(REMOVE_AT SET_VERBOSE_CACHE 0)
|
||||
join(doc ${SET_VERBOSE_CACHE})
|
||||
set(${SET_VERBOSE_UNPARSED_ARGUMENTS} CACHE ${type} ${doc})
|
||||
# cmake_parse_arguments is broken in CMake 3.4 (cannot parse CACHE) so use
|
||||
# list instead.
|
||||
list(GET ARGN 0 var)
|
||||
list(REMOVE_AT ARGN 0)
|
||||
list(GET ARGN 0 val)
|
||||
list(REMOVE_AT ARGN 0)
|
||||
list(REMOVE_AT ARGN 0)
|
||||
list(GET ARGN 0 type)
|
||||
list(REMOVE_AT ARGN 0)
|
||||
join(doc ${ARGN})
|
||||
set(${var} ${val} CACHE ${type} ${doc})
|
||||
endfunction()
|
||||
|
||||
# Set the default CMAKE_BUILD_TYPE to Release.
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
7.0.3 - 2020-08-06
|
||||
------------------
|
||||
|
||||
* Worked around broken ``numeric_limits`` for 128-bit integers
|
||||
(`#1787 <https://github.com/fmtlib/fmt/issues/1787>`_).
|
||||
|
||||
* Added error reporting on missing named arguments
|
||||
(`#1796 <https://github.com/fmtlib/fmt/issues/1796>`_).
|
||||
|
||||
* Stopped using 128-bit integers with clang-cl
|
||||
(`#1800 <https://github.com/fmtlib/fmt/pull/1800>`_).
|
||||
Thanks `@Kingcom <https://github.com/Kingcom>`_.
|
||||
|
||||
* Fixed issues in locale-specific integer formatting
|
||||
(`#1782 <https://github.com/fmtlib/fmt/issues/1782>`_,
|
||||
`#1801 <https://github.com/fmtlib/fmt/issues/1801>`_).
|
||||
|
||||
7.0.2 - 2020-07-29
|
||||
------------------
|
||||
|
||||
* Worked around broken ``numeric_limits`` for 128-bit integers
|
||||
(`#1725 <https://github.com/fmtlib/fmt/issues/1725>`_).
|
||||
|
||||
* Fixed compatibility with CMake 3.4
|
||||
(`#1779 <https://github.com/fmtlib/fmt/issues/1779>`_).
|
||||
|
||||
* Fixed handling of digit separators in locale-specific formatting
|
||||
(`#1782 <https://github.com/fmtlib/fmt/issues/1782>`_).
|
||||
|
||||
7.0.1 - 2020-07-07
|
||||
------------------
|
||||
|
||||
* Updated the inline version namespace name.
|
||||
|
||||
* Worked around a gcc bug in mangling of alias templates
|
||||
(`#1753 <https://github.com/fmtlib/fmt/issues/1753>`_).
|
||||
|
||||
* Fixed a linkage error on Windows
|
||||
(`#1757 <https://github.com/fmtlib/fmt/issues/1757>`_).
|
||||
Thanks `@Kurkin (Dmitry Kurkin) <https://github.com/Kurkin>`_.
|
||||
|
||||
* Fixed minor issues with the documentation.
|
||||
|
||||
7.0.0 - 2020-07-05
|
||||
------------------
|
||||
|
||||
@@ -126,7 +169,7 @@
|
||||
^
|
||||
|
||||
* Added sentinel support to ``fmt::join``
|
||||
(`#1689 <https://github.com/fmtlib/fmt/pull/1689>`_))
|
||||
(`#1689 <https://github.com/fmtlib/fmt/pull/1689>`_)
|
||||
|
||||
.. code:: c++
|
||||
|
||||
@@ -279,7 +322,7 @@
|
||||
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>`_,
|
||||
`@Kurkin (Dmitry Kurkin) <https://github.com/Kurkin>`_,
|
||||
`@invexed (James Beach) <https://github.com/invexed>`_,
|
||||
`@peterbell10 <https://github.com/peterbell10>`_,
|
||||
`@daixtrose (Markus Werle) <https://github.com/daixtrose>`_,
|
||||
|
||||
@@ -244,7 +244,7 @@ Output Iterator Support
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: fmt::format_to(OutputIt, const S&, Args&&...)
|
||||
.. doxygenfunction:: fmt::format_to_n(OutputIt, std::size_t, string_view, Args&&...)
|
||||
.. doxygenfunction:: fmt::format_to_n(OutputIt, size_t, const S&, const Args&...)
|
||||
.. doxygenstruct:: fmt::format_to_n_result
|
||||
:members:
|
||||
|
||||
@@ -274,7 +274,7 @@ Utilities
|
||||
|
||||
.. doxygenfunction:: fmt::join(const Range&, string_view)
|
||||
|
||||
.. doxygenfunction:: fmt::join(It, It, string_view)
|
||||
.. doxygenfunction:: fmt::join(It, Sentinel, string_view)
|
||||
|
||||
.. doxygenclass:: fmt::detail::buffer
|
||||
:members:
|
||||
|
||||
@@ -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']
|
||||
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']
|
||||
|
||||
def pip_install(package, commit=None, **kwargs):
|
||||
"Install package using pip."
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||
#define FMT_VERSION 70000
|
||||
#define FMT_VERSION 70003
|
||||
|
||||
#ifdef __clang__
|
||||
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
||||
@@ -188,12 +188,12 @@
|
||||
# define FMT_INLINE_NAMESPACE namespace
|
||||
# define FMT_END_NAMESPACE \
|
||||
} \
|
||||
using namespace v6; \
|
||||
using namespace v7; \
|
||||
}
|
||||
# endif
|
||||
# define FMT_BEGIN_NAMESPACE \
|
||||
namespace fmt { \
|
||||
FMT_INLINE_NAMESPACE v6 {
|
||||
FMT_INLINE_NAMESPACE v7 {
|
||||
#endif
|
||||
|
||||
#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
|
||||
@@ -299,7 +299,7 @@ template <typename T> struct std_string_view {};
|
||||
|
||||
#ifdef FMT_USE_INT128
|
||||
// Do nothing.
|
||||
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC
|
||||
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && !(FMT_CLANG_VERSION && FMT_MSC_VER)
|
||||
# define FMT_USE_INT128 1
|
||||
using int128_t = __int128_t;
|
||||
using uint128_t = __uint128_t;
|
||||
@@ -491,7 +491,7 @@ constexpr basic_string_view<typename S::char_type> to_string_view(const S& s) {
|
||||
|
||||
namespace detail {
|
||||
void to_string_view(...);
|
||||
using fmt::v6::to_string_view;
|
||||
using fmt::v7::to_string_view;
|
||||
|
||||
// Specifies whether S is a string type convertible to fmt::basic_string_view.
|
||||
// It should be a constexpr function but MSVC 2017 fails to compile it in
|
||||
@@ -1360,6 +1360,10 @@ using buffer_context =
|
||||
using format_context = buffer_context<char>;
|
||||
using wformat_context = buffer_context<wchar_t>;
|
||||
|
||||
// Workaround a bug in gcc: https://stackoverflow.com/q/62767544/471164.
|
||||
#define FMT_BUFFER_CONTEXT(Char) \
|
||||
basic_format_context<std::back_insert_iterator<detail::buffer<Char>>, Char>
|
||||
|
||||
/**
|
||||
\rst
|
||||
An array of references to arguments. It can be implicitly converted into
|
||||
@@ -1709,7 +1713,7 @@ template <typename Context> class basic_format_args {
|
||||
}
|
||||
|
||||
template <typename Char> int get_id(basic_string_view<Char> name) const {
|
||||
if (!has_named_args()) return {};
|
||||
if (!has_named_args()) return -1;
|
||||
const auto& named_args =
|
||||
(is_packed() ? values_[-1] : args_[-1].value_).named_args;
|
||||
for (size_t i = 0; i < named_args.size; ++i) {
|
||||
@@ -1765,12 +1769,12 @@ std::basic_string<Char> vformat(
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args);
|
||||
|
||||
std::string vformat(string_view format_str, format_args args);
|
||||
FMT_API std::string vformat(string_view format_str, format_args args);
|
||||
|
||||
template <typename Char>
|
||||
typename buffer_context<Char>::iterator vformat_to(
|
||||
typename FMT_BUFFER_CONTEXT(Char)::iterator vformat_to(
|
||||
buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args);
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args);
|
||||
|
||||
template <typename Char, typename Args,
|
||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
|
||||
@@ -283,6 +283,9 @@ template <typename T> constexpr T max_value() {
|
||||
template <typename T> constexpr int num_bits() {
|
||||
return std::numeric_limits<T>::digits;
|
||||
}
|
||||
// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
|
||||
template <> constexpr int num_bits<int128_t>() { return 128; }
|
||||
template <> constexpr int num_bits<uint128_t>() { return 128; }
|
||||
template <> constexpr int num_bits<fallback_uintptr>() {
|
||||
return static_cast<int>(sizeof(void*) *
|
||||
std::numeric_limits<unsigned char>::digits);
|
||||
@@ -721,13 +724,18 @@ class FMT_API format_error : public std::runtime_error {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
using is_signed =
|
||||
std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
|
||||
std::is_same<T, int128_t>::value>;
|
||||
|
||||
// Returns true if value is negative, false otherwise.
|
||||
// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
|
||||
template <typename T, FMT_ENABLE_IF(std::numeric_limits<T>::is_signed)>
|
||||
template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
|
||||
FMT_CONSTEXPR bool is_negative(T value) {
|
||||
return value < 0;
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(!std::numeric_limits<T>::is_signed)>
|
||||
template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
|
||||
FMT_CONSTEXPR bool is_negative(T) {
|
||||
return false;
|
||||
}
|
||||
@@ -742,9 +750,9 @@ FMT_CONSTEXPR bool is_supported_floating_point(T) {
|
||||
// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
|
||||
// represent all values of T.
|
||||
template <typename T>
|
||||
using uint32_or_64_or_128_t = conditional_t<
|
||||
std::numeric_limits<T>::digits <= 32, uint32_t,
|
||||
conditional_t<std::numeric_limits<T>::digits <= 64, uint64_t, uint128_t>>;
|
||||
using uint32_or_64_or_128_t =
|
||||
conditional_t<num_bits<T>() <= 32, uint32_t,
|
||||
conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
|
||||
|
||||
// Static data is placed in this class template for the header-only config.
|
||||
template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
|
||||
@@ -1559,7 +1567,7 @@ template <typename OutputIt, typename Char, typename UInt> struct int_writer {
|
||||
int num_digits = count_digits(abs_value);
|
||||
int size = num_digits, n = num_digits;
|
||||
std::string::const_iterator group = groups.cbegin();
|
||||
while (group != groups.cend() && num_digits > *group && *group > 0 &&
|
||||
while (group != groups.cend() && n > *group && *group > 0 &&
|
||||
*group != max_value<char>()) {
|
||||
size += sep_size;
|
||||
n -= *group;
|
||||
@@ -1590,7 +1598,11 @@ template <typename OutputIt, typename Char, typename UInt> struct int_writer {
|
||||
make_checked(p, s.size()));
|
||||
}
|
||||
if (prefix_size != 0) p[-1] = static_cast<Char>('-');
|
||||
write(out, basic_string_view<Char>(buffer.data(), buffer.size()), specs);
|
||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
||||
auto data = buffer.data();
|
||||
out = write_padded<align::right>(out, specs, size, size, [=](iterator it) {
|
||||
return copy_str<Char>(data, data + size, it);
|
||||
});
|
||||
}
|
||||
|
||||
void on_chr() { *out++ = static_cast<Char>(abs_value); }
|
||||
@@ -3482,9 +3494,9 @@ extern template int snprintf_float<long double>(long double value,
|
||||
|
||||
template <typename S, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||
inline typename buffer_context<Char>::iterator vformat_to(
|
||||
inline typename FMT_BUFFER_CONTEXT(Char)::iterator vformat_to(
|
||||
detail::buffer<Char>& buf, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args) {
|
||||
return detail::vformat_to(buf, to_string_view(format_str), args);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,9 @@ template FMT_API char detail::decimal_point_impl(locale_ref);
|
||||
|
||||
template FMT_API void detail::buffer<char>::append(const char*, const char*);
|
||||
|
||||
template FMT_API format_context::iterator detail::vformat_to(
|
||||
detail::buffer<char>&, string_view, basic_format_args<format_context>);
|
||||
template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
|
||||
detail::buffer<char>&, string_view,
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>);
|
||||
|
||||
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
|
||||
detail::buffer<char>&);
|
||||
|
||||
@@ -145,7 +145,24 @@ def update_site(env):
|
||||
b.data = b.data.replace('std::FILE*', 'std::FILE *')
|
||||
b.data = b.data.replace('unsigned int', 'unsigned')
|
||||
#b.data = b.data.replace('operator""_', 'operator"" _')
|
||||
b.data = b.data.replace(', size_t', ', std::size_t')
|
||||
b.data = b.data.replace(
|
||||
'format_to_n(OutputIt, size_t, string_view, Args&&',
|
||||
'format_to_n(OutputIt, size_t, const S&, const Args&')
|
||||
b.data = b.data.replace(
|
||||
'format_to_n(OutputIt, std::size_t, string_view, Args&&',
|
||||
'format_to_n(OutputIt, std::size_t, const S&, const Args&')
|
||||
if version == ('3.0.2'):
|
||||
b.data = b.data.replace(
|
||||
'fprintf(std::ostream&', 'fprintf(std::ostream &')
|
||||
if version == ('5.3.0'):
|
||||
b.data = b.data.replace(
|
||||
'format_to(OutputIt, const S&, const Args&...)',
|
||||
'format_to(OutputIt, const S &, const Args &...)')
|
||||
if version.startswith('5.') or version.startswith('6.'):
|
||||
b.data = b.data.replace(', size_t', ', std::size_t')
|
||||
if version.startswith('7.'):
|
||||
b.data = b.data.replace(', std::size_t', ', size_t')
|
||||
b.data = b.data.replace('join(It, It', 'join(It, Sentinel')
|
||||
b.data = b.data.replace('aa long', 'a long')
|
||||
b.data = b.data.replace('serveral', 'several')
|
||||
if version.startswith('6.2.'):
|
||||
|
||||
@@ -543,7 +543,6 @@ TEST(FormatterTest, ManyArgs) {
|
||||
TEST(FormatterTest, NamedArg) {
|
||||
EXPECT_EQ("1/a/A", format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'),
|
||||
fmt::arg("A_", "A"), fmt::arg("_1", 1)));
|
||||
EXPECT_THROW_MSG(format("{a}"), format_error, "argument not found");
|
||||
EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
|
||||
EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
|
||||
EXPECT_EQ("1 2", format("{} {two}", 1, fmt::arg("two", 2)));
|
||||
@@ -553,6 +552,8 @@ TEST(FormatterTest, NamedArg) {
|
||||
fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0),
|
||||
fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0),
|
||||
fmt::arg("o", 0), fmt::arg("p", 0)));
|
||||
EXPECT_THROW_MSG(format("{a}"), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format("{a}", 42), format_error, "argument not found");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, AutoArgIndex) {
|
||||
|
||||
@@ -61,12 +61,18 @@ TEST(LocaleTest, Format) {
|
||||
|
||||
std::locale special_grouping_loc(std::locale(), new special_grouping<char>());
|
||||
EXPECT_EQ("1,23,45,678", fmt::format(special_grouping_loc, "{:L}", 12345678));
|
||||
EXPECT_EQ("12,345", fmt::format(special_grouping_loc, "{:L}", 12345));
|
||||
|
||||
std::locale small_grouping_loc(std::locale(), new small_grouping<char>());
|
||||
EXPECT_EQ("4,2,9,4,9,6,7,2,9,5",
|
||||
fmt::format(small_grouping_loc, "{:L}", max_value<uint32_t>()));
|
||||
}
|
||||
|
||||
TEST(LocaleTest, FormatDetaultAlign) {
|
||||
std::locale special_grouping_loc(std::locale(), new special_grouping<char>());
|
||||
EXPECT_EQ(" 12,345", fmt::format(special_grouping_loc, "{:8L}", 12345));
|
||||
}
|
||||
|
||||
TEST(LocaleTest, WFormat) {
|
||||
std::locale loc(std::locale(), new numpunct<wchar_t>());
|
||||
EXPECT_EQ(L"1234567", fmt::format(std::locale(), L"{:L}", 1234567));
|
||||
@@ -88,4 +94,16 @@ TEST(LocaleTest, WFormat) {
|
||||
fmt::format(small_grouping_loc, L"{:L}", max_value<uint32_t>()));
|
||||
}
|
||||
|
||||
TEST(LocaleTest, DoubleFormatter) {
|
||||
auto loc = std::locale(std::locale(), new special_grouping<char>());
|
||||
auto f = fmt::formatter<int>();
|
||||
auto parse_ctx = fmt::format_parse_context("L");
|
||||
f.parse(parse_ctx);
|
||||
char buf[10] = {};
|
||||
fmt::basic_format_context<char*, char> format_ctx(
|
||||
buf, {}, fmt::detail::locale_ref(loc));
|
||||
*f.format(12345, format_ctx) = 0;
|
||||
EXPECT_STREQ("12,345", buf);
|
||||
}
|
||||
|
||||
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
|
||||
Reference in New Issue
Block a user