diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a37cb9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +.vscode/ +.vs/ + +*.iml +.idea/ +.externalNativeBuild/ +.gradle/ +gradle/ +gradlew* +local.properties +build/ +support/.cxx + +bin/ +/_CPack_Packages +/CMakeScripts +/doc/doxyxml +/doc/html +/doc/node_modules +virtualenv +/Testing +/install_manifest.txt +*~ +*.a +*.so* +*.xcodeproj +*.zip +cmake_install.cmake +CPack*.cmake +fmt-*.cmake +CTestTestfile.cmake +CMakeCache.txt +CMakeFiles +FMT.build +Makefile +run-msbuild.bat +fmt.pc diff --git a/ChangeLog.rst b/ChangeLog.rst index cf3d9df..644244d 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -1,3 +1,50 @@ +10.1.1 - 2023-08-26 +------------------- + +* Added formatters for ``std::atomic`` and ``atomic_flag`` + (`#3574 `_, + `#3594 `_). + Thanks `@wangzw (Zhanwei Wang) `_ and + `@AlexGuteniev (Alex Guteniev) `_. + +* Fixed an error about partial specialization of ``formatter`` + after instantiation when compiled with gcc and C++20 + (`#3584 `_). + +* Fixed compilation as a C++20 module with gcc and clang + (`#3587 `_, + `#3597 `_, + `#3605 `_). Thanks + `@MathewBensonCode (Mathew Benson) `_. + +* Made ``fmt::to_string`` work with types that have ``format_as`` overloads + (`#3575 `_). + Thanks `@phprus (Vladislav Shchapov) `_. + +* Made ``formatted_size`` work with integral format specifiers at compile time + (`#3591 `_). + Thanks `@elbeno (Ben Deane) `_. + +* Fixed a warning about the ``no_unique_address`` attribute on clang-cl + (`#3599 `_). + Thanks `@lukester1975 `_. + +* Improved compatibility with the legacy GBK encoding + (`#3598 `_, + `#3599 `_). + Thanks `@YuHuanTin `_. + +* Added OpenSSF Scorecard analysis + (`#3530 `_, + `#3571 `_). + Thanks `@joycebrum (Joyce) `_. + +* Updated CI dependencies + (`#3591 `_, + `#3592 `_, + `#3593 `_, + `#3602 `_). + 10.1.0 - 2023-08-12 ------------------- @@ -103,6 +150,9 @@ Thanks `@gix (Nico Rieck) `_, `@hmbj (Hans-Martin B. Jensen) `_. +* Added support for the ``?`` format specifier to ``std::filesystem::path`` and + made the default unescaped for consistency with strings. + * Deprecated the wide stream overload of ``printf``. * Removed unused ``basic_printf_parse_context``. diff --git a/README.rst b/README.rst index f51fefa..44bb686 100644 --- a/README.rst +++ b/README.rst @@ -22,6 +22,9 @@ :alt: Ask questions at StackOverflow with the tag fmt :target: https://stackoverflow.com/questions/tagged/fmt +.. image:: https://api.securityscorecards.dev/projects/github.com/fmtlib/fmt/badge + :target: https://securityscorecards.dev/viewer/?uri=github.com/fmtlib/fmt + **{fmt}** is an open-source formatting library providing a fast and safe alternative to C stdio and C++ iostreams. diff --git a/debian/changelog b/debian/changelog index eebb513..c909fe5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +fmtlib (10.1.1+ds1-2) experimental; urgency=medium + + * Fix build with Sphinx 7 (Closes: #1042588) + + -- Shengjing Zhu Wed, 22 Nov 2023 04:18:37 +0800 + +fmtlib (10.1.1+ds1-1) experimental; urgency=medium + + * New upstream version 10.1.1+ds1 + + -- Shengjing Zhu Fri, 08 Sep 2023 14:47:55 +0800 + fmtlib (10.1.0+ds1-1) experimental; urgency=medium * New upstream version 10.1.0+ds1 diff --git a/debian/patches/0002-Privacy-README.rst.patch b/debian/patches/0002-Privacy-README.rst.patch index 750a165..0052c2f 100644 --- a/debian/patches/0002-Privacy-README.rst.patch +++ b/debian/patches/0002-Privacy-README.rst.patch @@ -4,14 +4,14 @@ Subject: Privacy: README.rst Forwarded: not-needed --- - README.rst | 24 ------------------------ - 1 file changed, 24 deletions(-) + README.rst | 27 --------------------------- + 1 file changed, 27 deletions(-) diff --git a/README.rst b/README.rst -index 6a639b6..e89f81f 100644 +index 44bb686..3f04146 100644 --- a/README.rst +++ b/README.rst -@@ -1,27 +1,3 @@ +@@ -1,30 +1,3 @@ -.. image:: https://user-images.githubusercontent.com/ - 576385/156254208-f5b743a9-88cf-439d-b0c0-923d53e8d551.png - :width: 25% @@ -35,6 +35,9 @@ index 6a639b6..e89f81f 100644 -.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg - :alt: Ask questions at StackOverflow with the tag fmt - :target: https://stackoverflow.com/questions/tagged/fmt +- +-.. image:: https://api.securityscorecards.dev/projects/github.com/fmtlib/fmt/badge +- :target: https://securityscorecards.dev/viewer/?uri=github.com/fmtlib/fmt - **{fmt}** is an open-source formatting library providing a fast and safe alternative to C stdio and C++ iostreams. diff --git a/debian/patches/0006-Doc-build-with-Sphinx-7.patch b/debian/patches/0006-Doc-build-with-Sphinx-7.patch new file mode 100644 index 0000000..d6e8b0e --- /dev/null +++ b/debian/patches/0006-Doc-build-with-Sphinx-7.patch @@ -0,0 +1,29 @@ +From: Shengjing Zhu +Date: Wed, 22 Nov 2023 04:17:40 +0800 +Subject: Doc: build with Sphinx 7 + +--- + doc/basic-bootstrap/layout.html | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/doc/basic-bootstrap/layout.html b/doc/basic-bootstrap/layout.html +index 5519c4b..a6e7914 100644 +--- a/doc/basic-bootstrap/layout.html ++++ b/doc/basic-bootstrap/layout.html +@@ -102,14 +102,14 @@ + {%- endmacro %} + + {%- macro css() %} +- ++ + + {%- for cssfile in css_files %} + + {%- endfor %} + {%- endmacro %} + +- ++ + + + diff --git a/debian/patches/series b/debian/patches/series index f1d38a1..7c13966 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -3,3 +3,4 @@ 0003-Privacy-GA-in-doc-layout.html.patch 0004-Doc-unwanted-download-links-in-doc-layout.html.patch 0005-Doc-unwanted-GitHub-iframe.patch +0006-Doc-build-with-Sphinx-7.patch diff --git a/doc/build.py b/doc/build.py index 98716a6..4c4a331 100755 --- a/doc/build.py +++ b/doc/build.py @@ -4,7 +4,7 @@ import errno, os, re, sys from subprocess import check_call, CalledProcessError, Popen, PIPE, STDOUT -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', '7.1.2', '7.1.3', '8.0.0', '8.0.1', '8.1.0', '8.1.1', '9.0.0', '9.1.0', '10.0.0', '10.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', '7.1.2', '7.1.3', '8.0.0', '8.0.1', '8.1.0', '8.1.1', '9.0.0', '9.1.0', '10.0.0', '10.1.0', '10.1.1'] class Pip: def __init__(self, venv_dir): diff --git a/include/fmt/core.h b/include/fmt/core.h index bfdca5f..1fe1388 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -1420,9 +1420,8 @@ template struct arg_mapper { FMT_ENABLE_IF( std::is_pointer::value || std::is_member_pointer::value || std::is_function::type>::value || - (std::is_convertible::value && - !std::is_convertible::value && - !has_formatter::value))> + (std::is_array::value && + !std::is_convertible::value))> FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer { return {}; } @@ -1662,7 +1661,6 @@ template class basic_format_arg { \endrst */ // DEPRECATED! -FMT_EXPORT template FMT_CONSTEXPR FMT_INLINE auto visit_format_arg( Visitor&& vis, const basic_format_arg& arg) -> decltype(vis(0)) { diff --git a/include/fmt/format.h b/include/fmt/format.h index e5bd8b1..87a34b9 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -83,7 +83,8 @@ # if FMT_CPLUSPLUS >= 202002L # if FMT_HAS_CPP_ATTRIBUTE(no_unique_address) # define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]] -# elif FMT_MSC_VERSION >= 1929 // VS2019 v16.10 and later +// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485) +# elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION # define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] # endif # endif @@ -368,8 +369,6 @@ class uint128_fallback { private: uint64_t lo_, hi_; - friend uint128_fallback umul128(uint64_t x, uint64_t y) noexcept; - public: constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {} @@ -1038,6 +1037,7 @@ namespace detail { FMT_API bool write_console(std::FILE* f, string_view text); FMT_API void print(std::FILE*, string_view); } // namespace detail + FMT_BEGIN_EXPORT // Suppress a misleading warning in older versions of clang. @@ -1387,8 +1387,8 @@ FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits, } template -inline auto format_uint(It out, UInt value, int num_digits, bool upper = false) - -> It { +FMT_CONSTEXPR inline auto format_uint(It out, UInt value, int num_digits, + bool upper = false) -> It { if (auto ptr = to_pointer(out, to_unsigned(num_digits))) { format_uint(ptr, value, num_digits, upper); return out; @@ -1453,7 +1453,7 @@ template class to_utf8 { ++p; if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) { if (policy == to_utf8_error_policy::abort) return false; - buf.append(string_view("�")); + buf.append(string_view("\xEF\xBF\xBD")); --p; } else { c = (c << 10) + static_cast(*p) - 0x35fdc00; @@ -1486,9 +1486,9 @@ inline uint128_fallback umul128(uint64_t x, uint64_t y) noexcept { auto p = static_cast(x) * static_cast(y); return {static_cast(p >> 64), static_cast(p)}; #elif defined(_MSC_VER) && defined(_M_X64) - auto result = uint128_fallback(); - result.lo_ = _umul128(x, y, &result.hi_); - return result; + auto hi = uint64_t(); + auto lo = _umul128(x, y, &hi); + return {hi, lo}; #else const uint64_t mask = static_cast(max_value()); @@ -4287,7 +4287,8 @@ auto join(Range&& range, string_view sep) std::string answer = fmt::to_string(42); \endrst */ -template ::value)> +template ::value && + !detail::has_format_as::value)> inline auto to_string(const T& value) -> std::string { auto buffer = memory_buffer(); detail::write(appender(buffer), value); @@ -4312,6 +4313,14 @@ FMT_NODISCARD auto to_string(const basic_memory_buffer& buf) return std::basic_string(buf.data(), size); } +template ::value && + detail::has_format_as::value)> +inline auto to_string(const T& value) -> std::string { + return to_string(format_as(value)); +} + +FMT_END_EXPORT + namespace detail { template @@ -4383,6 +4392,8 @@ void vformat_to(buffer& buf, basic_string_view fmt, detail::parse_format_string(fmt, format_handler(out, fmt, args, loc)); } +FMT_BEGIN_EXPORT + #ifndef FMT_HEADER_ONLY extern template FMT_API void vformat_to(buffer&, string_view, typename vformat_args<>::type, diff --git a/include/fmt/std.h b/include/fmt/std.h index b0e78e1..b4e055c 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -8,6 +8,7 @@ #ifndef FMT_STD_H_ #define FMT_STD_H_ +#include #include #include #include @@ -435,6 +436,30 @@ struct formatter +struct formatter, Char, + enable_if_t::value>> + : formatter { + template + auto format(const std::atomic& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.load(), ctx); + } +}; + +#ifdef __cpp_lib_atomic_flag_test +FMT_EXPORT +template +struct formatter + : formatter { + template + auto format(const std::atomic_flag& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.test(), ctx); + } +}; +#endif // __cpp_lib_atomic_flag_test +FMT_END_NAMESPACE #endif // FMT_STD_H_ diff --git a/test/compile-test.cc b/test/compile-test.cc index f85d2d8..d6c7c64 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -199,6 +199,21 @@ TEST(compile_test, format_to_n) { TEST(compile_test, constexpr_formatted_size) { FMT_CONSTEXPR20 size_t size = fmt::formatted_size(FMT_COMPILE("{}"), 42); EXPECT_EQ(size, 2); + FMT_CONSTEXPR20 size_t hex_size = + fmt::formatted_size(FMT_COMPILE("{:x}"), 15); + EXPECT_EQ(hex_size, 1); + FMT_CONSTEXPR20 size_t binary_size = + fmt::formatted_size(FMT_COMPILE("{:b}"), 15); + EXPECT_EQ(binary_size, 4); + FMT_CONSTEXPR20 size_t padded_size = + fmt::formatted_size(FMT_COMPILE("{:*^6}"), 42); + EXPECT_EQ(padded_size, 6); + FMT_CONSTEXPR20 size_t float_size = + fmt::formatted_size(FMT_COMPILE("{:.3}"), 12.345); + EXPECT_EQ(float_size, 4); + FMT_CONSTEXPR20 size_t str_size = + fmt::formatted_size(FMT_COMPILE("{:s}"), "abc"); + EXPECT_EQ(str_size, 3); } # endif diff --git a/test/format-test.cc b/test/format-test.cc index d148e74..dd38817 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2141,6 +2141,13 @@ TEST(format_test, format_as) { EXPECT_EQ(fmt::format("{}", test::struct_as_int()), "42"); } +TEST(format_test, format_as_to_string) { + EXPECT_EQ(fmt::to_string(test::scoped_enum_as_int()), "42"); + EXPECT_EQ(fmt::to_string(test::scoped_enum_as_string_view()), "foo"); + EXPECT_EQ(fmt::to_string(test::scoped_enum_as_string()), "foo"); + EXPECT_EQ(fmt::to_string(test::struct_as_int()), "42"); +} + template bool check_enabled_formatter() { static_assert(std::is_default_constructible>::value, ""); diff --git a/test/std-test.cc b/test/std-test.cc index 17b4792..56904cc 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -236,3 +236,22 @@ TEST(std_test, format_const_bit_reference) { const std::vector v = {true, false}; EXPECT_EQ(fmt::format("{} {}", v[0], v[1]), "true false"); } + +TEST(std_test, format_atomic) { + std::atomic b(false); + EXPECT_EQ(fmt::format("{}", b), "false"); + + const std::atomic cb(true); + EXPECT_EQ(fmt::format("{}", cb), "true"); +} + +#ifdef __cpp_lib_atomic_flag_test +TEST(std_test, format_atomic_flag) { + std::atomic_flag f = ATOMIC_FLAG_INIT; + (void) f.test_and_set(); + EXPECT_EQ(fmt::format("{}", f), "true"); + + const std::atomic_flag cf = ATOMIC_FLAG_INIT; + EXPECT_EQ(fmt::format("{}", cf), "false"); +} +#endif // __cpp_lib_atomic_flag_test