Skip to content

Commit

Permalink
Merge branch 'fmtlib:master' into zig-pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
kassane committed Jul 7, 2024
2 parents aa766d4 + 7a8b54a commit bb91bf5
Show file tree
Hide file tree
Showing 13 changed files with 228 additions and 213 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ jobs:

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
with:
sarif_file: results.sarif
14 changes: 9 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,14 @@ endif ()
add_library(fmt-header-only INTERFACE)
add_library(fmt::fmt-header-only ALIAS fmt-header-only)

if (MSVC AND FMT_UNICODE)
if (NOT MSVC)
# Unicode is always supported on compilers other than MSVC.
elseif (FMT_UNICODE)
# Unicode support requires compiling with /utf-8.
target_compile_options(fmt PUBLIC $<$<COMPILE_LANGUAGE:CXX>:/utf-8>)
target_compile_options(fmt-header-only INTERFACE $<$<COMPILE_LANGUAGE:CXX>:/utf-8>)
else ()
target_compile_definitions(fmt PUBLIC FMT_UNICODE=0)
endif ()

target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
Expand Down Expand Up @@ -464,12 +468,13 @@ function(add_doc_target)
${CMAKE_COMMAND}
-E env PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}/support/python
${MKDOCS} build -f ${CMAKE_CURRENT_SOURCE_DIR}/support/mkdocs.yml
--site-dir ${CMAKE_CURRENT_BINARY_DIR}/site
# MkDocs requires the site dir to be outside of the doc dir.
--site-dir ${CMAKE_CURRENT_BINARY_DIR}/doc-html
--no-directory-urls
SOURCES ${sources})

include(GNUInstallDirs)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/support/site/
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt OPTIONAL)
endfunction()

Expand Down Expand Up @@ -504,8 +509,7 @@ if (FMT_MASTER_PROJECT AND EXISTS ${gitignore})
string(REPLACE "*" ".*" line "${line}")
set(ignored_files ${ignored_files} "${line}$" "${line}/")
endforeach ()
set(ignored_files ${ignored_files}
/.git /breathe /format-benchmark sphinx/ .buildinfo .doctrees)
set(ignored_files ${ignored_files} /.git /build/doxyxml .vagrant)

set(CPACK_SOURCE_GENERATOR ZIP)
set(CPACK_SOURCE_IGNORE_FILES ${ignored_files})
Expand Down
71 changes: 52 additions & 19 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@
# 11.0.0 - TBD
# 11.0.1 - 2024-07-05

- Fixed version number in the inline namespace
(https://github.com/fmtlib/fmt/issues/4047).

- Fixed disabling Unicode support via CMake
(https://github.com/fmtlib/fmt/issues/4051).

- Fixed deprecated `visit_format_arg` (https://github.com/fmtlib/fmt/pull/4043).
Thanks @nebkat.

- Fixed handling of a sign and improved the `std::complex` formater
(https://github.com/fmtlib/fmt/pull/4034,
https://github.com/fmtlib/fmt/pull/4050). Thanks @tesch1 and @phprus.

- Removed a redundant check in the formatter for `std::expected`
(https://github.com/fmtlib/fmt/pull/4040). Thanks @phprus.

# 11.0.0 - 2024-07-01

- Added `fmt/base.h` which provides a subset of the API with minimal include
dependencies and enough functionality to replace all uses of `*printf`.
This brings the compile time of code using {fmt} much closer to the
equivalent `printf` code as shown on the following benchmark that compiles
100 source files:
dependencies and enough functionality to replace all uses of the `printf`
family of functions. This brings the compile time of code using {fmt} much
closer to the equivalent `printf` code as shown on the following benchmark
that compiles 100 source files:

| Method | Compile Time (s) |
|--------------|------------------|
| printf | 1.6 |
| IOStreams | 25.9 |
| fmt | 4.8 |
| fmt 10.x | 19.0 |
| fmt 11.0 | 4.8 |
| tinyformat | 29.1 |
| Boost Format | 55.0 |

Note that this is purely formatting code and includes. In real projects the
difference will be smaller partly because common standard headers will be
included in almost any translation unit anyway.
This gives almost 4x improvement in build speed compared to version 10.
Note that the benchmark is purely formatting code and includes. In real
projects the difference from `printf` will be smaller partly because common
standard headers will be included in almost any translation unit (TU) anyway.
In particular, in every case except `printf` above ~1s is spent in total on
including `<type_traits>` in all TUs.

- Optimized includes in other headers such as `fmt/format.h` which is now
roughly equivalent to the old `fmt/core.h`.
roughly equivalent to the old `fmt/core.h` in terms of build speed.

- Migrated the documentation at https://fmt.dev/ from Sphinx to MkDocs.

- Improved C++20 module support
(https://github.com/fmtlib/fmt/issues/3990,
Expand All @@ -31,8 +55,10 @@
https://github.com/fmtlib/fmt/pull/4004,
https://github.com/fmtlib/fmt/pull/4005,
https://github.com/fmtlib/fmt/pull/4006,
https://github.com/fmtlib/fmt/pull/4013). In particular, native CMake support
for modules is now used if available. Thanks @yujincheng08.
https://github.com/fmtlib/fmt/pull/4013,
https://github.com/fmtlib/fmt/pull/4027,
https://github.com/fmtlib/fmt/pull/4029). In particular, native CMake support
for modules is now used if available. Thanks @yujincheng08 and @matt77hias.

- Added an option to replace standard includes with `import std` enabled via
the `FMT_IMPORT_STD` macro (https://github.com/fmtlib/fmt/issues/3921,
Expand Down Expand Up @@ -60,11 +86,11 @@
Benchmark Time CPU Iterations
-------------------------------------------------------
printf 81.8 ns 81.5 ns 8496899
fmt::print (10.*) 63.8 ns 61.9 ns 11524151
fmt::print (10.x) 63.8 ns 61.9 ns 11524151
fmt::print (11.0) 51.3 ns 51.0 ns 13846580
```

- Improved safety of `fmt::format_to` when writting to an array
- Improved safety of `fmt::format_to` when writing to an array
(https://github.com/fmtlib/fmt/pull/3805).
For example ([godbolt](https://www.godbolt.org/z/cYrn8dWY8)):

Expand All @@ -73,7 +99,7 @@
auto result = fmt::format_to(volkswagen, "elephant");
```

no longer results in a buffer oveflow. Instead the output will be truncated
no longer results in a buffer overflow. Instead the output will be truncated
and you can get the end iterator and whether truncation occurred from the
`result` object. Thanks @ThePhD.

Expand All @@ -86,7 +112,7 @@
compiled with Unicode enabled.

- Added a formatter for `std::expected`
(https://github.com/fmtlib/fmt/pull/3834. Thanks @dominicpoeschko.
(https://github.com/fmtlib/fmt/pull/3834). Thanks @dominicpoeschko.

- Added a formatter for `std::complex`
(https://github.com/fmtlib/fmt/issues/1467,
Expand Down Expand Up @@ -164,7 +190,7 @@
- Moved range and iterator overloads of `fmt::join` to `fmt/ranges.h`, next
to other overloads.
- Fixed hanling of types with `begin` returning `void` such as Eigen matrices
- Fixed handling of types with `begin` returning `void` such as Eigen matrices
(https://github.com/fmtlib/fmt/issues/3839,
https://github.com/fmtlib/fmt/pull/3964). Thanks @Arghnews.
Expand Down Expand Up @@ -215,7 +241,7 @@
- Improved named argument validation
(https://github.com/fmtlib/fmt/issues/3817).
- Disabled copy contruction/assignment for `fmt::format_arg_store` and
- Disabled copy construction/assignment for `fmt::format_arg_store` and
fixed moved construction (https://github.com/fmtlib/fmt/pull/3833).
Thanks @ivafanas.
Expand Down Expand Up @@ -255,7 +281,8 @@
https://github.com/fmtlib/fmt/pull/3980,
https://github.com/fmtlib/fmt/pull/3988,
https://github.com/fmtlib/fmt/pull/4010,
https://github.com/fmtlib/fmt/pull/4012).
https://github.com/fmtlib/fmt/pull/4012,
https://github.com/fmtlib/fmt/pull/4038).
Thanks @vgorrX, @waywardmonkeys, @tchaikov and @phprus.
- Fixed buffer overflow when using format string compilation with debug format
Expand Down Expand Up @@ -310,7 +337,9 @@
https://github.com/fmtlib/fmt/pull/3968,
https://github.com/fmtlib/fmt/pull/3972,
https://github.com/fmtlib/fmt/pull/3983,
https://github.com/fmtlib/fmt/issues/3992,
https://github.com/fmtlib/fmt/pull/3995,
https://github.com/fmtlib/fmt/pull/4009,
https://github.com/fmtlib/fmt/pull/4023).
Thanks @hmbj, @phprus, @res2k, @Baardi, @matt77hias, @waywardmonkeys, @hmbj,
@yakra, @prlw1, @Arghnews, @mtillmann0, @ShifftC, @eepp, @jimmy-park and
Expand Down Expand Up @@ -483,6 +512,10 @@
- Made `fmt::streamed` `constexpr`.
(https://github.com/fmtlib/fmt/pull/3650). Thanks @muggenhor.
- Made `fmt::format_int` `constexpr`
(https://github.com/fmtlib/fmt/issues/4031,
https://github.com/fmtlib/fmt/pull/4032). Thanks @dixlorenz.
- Enabled `consteval` on older versions of MSVC
(https://github.com/fmtlib/fmt/pull/3757). Thanks @phprus.
Expand Down
10 changes: 5 additions & 5 deletions include/fmt/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# define FMT_MODULE
#endif

// c headers are preferable for performance reasons
#ifndef FMT_MODULE
# include <limits.h> // CHAR_BIT
# include <stdio.h> // FILE
Expand All @@ -24,7 +23,7 @@
#endif

// The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 100202
#define FMT_VERSION 110001

// Detect compiler versions.
#if defined(__clang__) && !defined(__ibmxl__)
Expand Down Expand Up @@ -263,7 +262,7 @@
#ifndef FMT_BEGIN_NAMESPACE
# define FMT_BEGIN_NAMESPACE \
namespace fmt { \
inline namespace v10 {
inline namespace v11 {
# define FMT_END_NAMESPACE \
} \
}
Expand Down Expand Up @@ -442,7 +441,8 @@ struct is_std_string_like : std::false_type {};
template <typename T>
struct is_std_string_like<T, void_t<decltype(std::declval<T>().find_first_of(
typename T::value_type(), 0))>>
: std::true_type {};
: std::is_convertible<decltype(std::declval<T>().data()),
const typename T::value_type*> {};

// Returns true iff the literal encoding is UTF-8.
constexpr auto is_utf8_enabled() -> bool {
Expand Down Expand Up @@ -1761,7 +1761,7 @@ template <typename Context> class basic_format_arg {
* `vis(value)` will be called with the value of type `double`.
*/
template <typename Visitor>
FMT_CONSTEXPR auto visit(Visitor&& vis) -> decltype(vis(0)) {
FMT_CONSTEXPR auto visit(Visitor&& vis) const -> decltype(vis(0)) {
switch (type_) {
case detail::type::none_type:
break;
Expand Down
4 changes: 2 additions & 2 deletions include/fmt/printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,8 @@ using wprintf_args = basic_format_args<wprintf_context>;
/// arguments and can be implicitly converted to `printf_args`.
template <typename Char = char, typename... T>
inline auto make_printf_args(T&... args)
-> decltype(make_format_args<basic_printf_context<Char>>(args...)) {
return make_format_args<basic_printf_context<Char>>(args...);
-> decltype(fmt::make_format_args<basic_printf_context<Char>>(args...)) {
return fmt::make_format_args<basic_printf_context<Char>>(args...);
}

template <typename Char> struct vprintf_args {
Expand Down
78 changes: 56 additions & 22 deletions include/fmt/std.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ struct formatter<std::expected<T, E>, Char,

if (value.has_value()) {
out = detail::write<Char>(out, "expected(");
out = detail::write_escaped_alternative<Char>(out, value.value());
out = detail::write_escaped_alternative<Char>(out, *value);
} else {
out = detail::write<Char>(out, "unexpected(");
out = detail::write_escaped_alternative<Char>(out, value.error());
Expand Down Expand Up @@ -631,33 +631,67 @@ struct formatter<std::atomic_flag, Char> : formatter<bool, Char> {
#endif // __cpp_lib_atomic_flag_test

FMT_EXPORT
template <typename F, typename Char>
struct formatter<std::complex<F>, Char> : nested_formatter<F, Char> {
template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
private:
// Functor because C++11 doesn't support generic lambdas.
struct writer {
const formatter<std::complex<F>, Char>* f;
const std::complex<F>& c;

template <typename OutputIt>
FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt {
if (c.real() != 0) {
auto format_full = detail::string_literal<Char, '(', '{', '}', '+', '{',
'}', 'i', ')'>{};
return fmt::format_to(out, basic_string_view<Char>(format_full),
f->nested(c.real()), f->nested(c.imag()));
}
auto format_imag = detail::string_literal<Char, '{', '}', 'i'>{};
return fmt::format_to(out, basic_string_view<Char>(format_imag),
f->nested(c.imag()));
detail::dynamic_format_specs<Char> specs_;

template <typename FormatContext, typename OutputIt>
FMT_CONSTEXPR auto do_format(const std::complex<T>& c,
detail::dynamic_format_specs<Char>& specs,
FormatContext& ctx, OutputIt out) const
-> OutputIt {
if (c.real() != 0) {
*out++ = Char('(');
out = detail::write<Char>(out, c.real(), specs, ctx.locale());
specs.sign = sign::plus;
out = detail::write<Char>(out, c.imag(), specs, ctx.locale());
if (!detail::isfinite(c.imag())) *out++ = Char(' ');
*out++ = Char('i');
*out++ = Char(')');
return out;
}
};
out = detail::write<Char>(out, c.imag(), specs, ctx.locale());
if (!detail::isfinite(c.imag())) *out++ = Char(' ');
*out++ = Char('i');
return out;
}

public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin();
return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
detail::type_constant<T, Char>::value);
}

template <typename FormatContext>
auto format(const std::complex<F>& c, FormatContext& ctx) const
auto format(const std::complex<T>& c, FormatContext& ctx) const
-> decltype(ctx.out()) {
return this->write_padded(ctx, writer{this, c});
auto specs = specs_;
if (specs.width_ref.kind != detail::arg_id_kind::none ||
specs.precision_ref.kind != detail::arg_id_kind::none) {
detail::handle_dynamic_spec<detail::width_checker>(specs.width,
specs.width_ref, ctx);
detail::handle_dynamic_spec<detail::precision_checker>(
specs.precision, specs.precision_ref, ctx);
}

if (specs.width == 0) return do_format(c, specs, ctx, ctx.out());
auto buf = basic_memory_buffer<Char>();

auto outer_specs = format_specs();
outer_specs.width = specs.width;
outer_specs.fill = specs.fill;
outer_specs.align = specs.align;

specs.width = 0;
specs.fill = {};
specs.align = align::none;

do_format(c, specs, ctx, basic_appender<Char>(buf));
return detail::write<Char>(ctx.out(),
basic_string_view<Char>(buf.data(), buf.size()),
outer_specs);
}
};

Expand Down
5 changes: 2 additions & 3 deletions support/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

# A vagrant config for testing against gcc-4.8.
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.disksize.size = '15GB'
config.vm.box = "bento/ubuntu-22.04-arm64"

config.vm.provider "virtualbox" do |vb|
config.vm.provider "vmware_desktop" do |vb|
vb.memory = "4096"
end

Expand Down
Loading

0 comments on commit bb91bf5

Please sign in to comment.