From 5ff285a9ed91944b686cd1d77ff28bafa9975695 Mon Sep 17 00:00:00 2001
From: Simone <91993281+SimoneN64@users.noreply.github.com>
Date: Tue, 7 Jan 2025 15:10:49 +0000
Subject: [PATCH] Squashed 'external/fmt/' changes from 3b70966df..093b39ca5
093b39ca5 Update docs for meson (#4291)
2c3a5698e Simplify a copying the fill from basic_specs
fc1b0f348 Clarify use of FMT_THROW in a comment
1d066890c Resolve C4702 unreachable code warnings
dad323751 Fix a bug when copying the fill from basic_specs
880e1494d Improve xchar support for std::bitset formatter
e3ddede6c Update version
e9ec4fdc8 Bump version
feb72126b Readd FMT_NO_UNIQUE_ADDRESS
8d517e54c Update changelog
563fc74ae Update changelog
3e04222d5 Restore ABI compatibility with 11.0.2
853df39d0 Mention compile-time formatting
11742a09c Clarify that format_string should be used instead of fstring
da24fac10 Document fstring
5fa4bdd75 Define CMake components to allow docs to be installed separately (#4276)
3c8aad8df Update the release script
0e8aad961 Update version
debe784aa Update changelog
f6d112567 Update changelog
73d0d3f75 Fix github API call
08f60f1ef Update changelog
faf3f8408 Bump version
f3a41441d Replace requests with urllib
3f33cb21d Update changelog
b07a90386 Update changelog
a6fba5177 Update changelog
25e292998 Update changelog
00ab2e98b Update changelog
a3ef285ae Always inline const_check to improve debug codegen in clang
28d1abc9d Update changelog
90704b9ef Update changelog
86dae01c2 Fix compatibility with older versions of VS (#4271)
d8a79eafd Document formatting of bit-fields and fields of packed structs
7c3d0152e Use the _MSVC_STL_UPDATE macro to detect STL (#4267)
7c50da538 Allow getting size of dynamic format arg store (#4270)
873670ba3 Make parameter basic_memory_buffer& buf of to_string const
735d4cc05 Update changelog
141380172 Allow disabling by define FMT_CPP_LIB_FILESYSTEM=0 (#4259)
4302d7429 Update changelog
0f51ea79d Update changelog
9600fee02 Include only if FMT_CPP_LIB_FILESYSTEM is set (#4258)
47a66c5ec Bump msys2/setup-msys2 from 2.24.0 to 2.25.0 (#4250)
385c01dc7 Allow bit_cast to work for 80bit long double (#4246)
df249d8ad Remove an old workaround
dfad80d1c Remove an old workaround
536cabd56 Export all range join overloads (#4239)
b1a054706 Remove more MSVC 2015 workarounds and fix string_view checks
bfd95392c Remove MSVC 2015 workaround
9ced61bca Replace std::forward for clang-tidy (#4236)
75e5be6ad Sort specifiers
a169d7fa4 Fix chrono formatting syntax doc (#4235)
a6c45dfea Fix modular build
a35389b3c Corrently handle buffer flush
5a3576acc Implement fmt::join for tuple-like objects (#4230)
542600013 Suppress MSVC warnings "C4127: conditional expression is constant" by used const_check (#4233)
720da57ba Remove reference to unused intrinsic
680db66c3 Explicitly export symbols from detail
56ce41ef6 Remove initializer_list dependency
cf50e4d6a Fix const[expr] in context API
6580d7b80 Cleanup the format API
7e73566ce Minor cleanup
8523dba2d Make constexpr precede explicit consistently
e3d3b24fc Minor cleanup
1521bba70 Use consistent types for argument count
00649552a Bump github/codeql-action from 3.26.6 to 3.27.0 (#4223)
4b8e2838f More cleanup
7d4662f7a Remove FMT_BUILTIN_CTZ
27110bc47 Minor cleanup
68f315376 Fix narrowing conversion warning in struct fstring (#4210)
168df9a06 Implement fmt::format_to into std::vector (#4211)
4daa3d591 Fix error: cannot use 'try' with exceptions disabled in Win LLVM Clang (#4208)
e9eaa27e5 Add std::exception to the docs
2b6a786e3 Use standard context in print
a16ff5787 Add support for code units > 0xFFFF in fill
601be1cbe Add support for code units > 0xFFFF in fill
58c185b63 Changing type of data_ to size_t to avoid compilation warnings (#4200)
a0a9ba2af Fix hashes
cc2ba8f9e Cleanup cifuzz action
a18d42b20 Simplify lint (#4197)
4046f9727 Fix -Wmissing-noreturn warning (#4194)
6bdc12a19 detail_exported -> detail
786a4b096 Cleanup fixed_string
2cb3b7c64 Update README.md
e9cba6905 Update README.md
02537548f Cleanup an example
c68c5fa7c Test FMT_BUILTIN_TYPES
22701d5f6 Address build failures when using Tip-of-Tree clang. (#4187)
e62c41ffb Conform `std::iterator_traits` to [iterator.traits]/1 (#4185)
18792893d Silencing Wextra-semi warning (#4188)
c90bc9186 Bump actions/checkout from 4.1.6 to 4.2.0 (#4182)
c95722ad6 Improve naming consistency
db06b0df8 Use countl_zero in bigint
b9ec48d9c Cleanup bigint
3faf6f181 Add min_of/max_of
d64b100a3 Relax constexpr
ff9ee0461 Fix handling FMT_BUILTIN_TYPES
1c5883bef Test nondeterministic conversion to format string
cacc3108c Don't assume repeated evaluation of string literal produce the same pointer
fade652ad Require clang >=15 for _BitInt support (#4176)
96dca569a Module linkage fixes for shared build (#4169)
891c9a73a Cleanup format API
9282222b7 Export more
e5b20ff0d Deprecate detail::locale_ref
ff9222354 Simplify locale handling
80c4d42c6 Cleanup format.h
git-subtree-dir: external/fmt
git-subtree-split: 093b39ca5eea129b111060839602bcfaf295125a
---
.github/workflows/cifuzz.yml | 6 +-
.github/workflows/doc.yml | 2 +-
.github/workflows/lint.yml | 12 +-
.github/workflows/linux.yml | 2 +-
.github/workflows/macos.yml | 2 +-
.github/workflows/scorecard.yml | 4 +-
.github/workflows/windows.yml | 6 +-
CMakeLists.txt | 19 +-
ChangeLog.md | 238 +++++++++-
README.md | 1 +
doc/api.md | 75 ++--
doc/get-started.md | 2 +-
doc/index.md | 4 +-
doc/syntax.md | 6 +-
include/fmt/args.h | 3 +
include/fmt/base.h | 180 +++++---
include/fmt/chrono.h | 40 +-
include/fmt/compile.h | 13 +-
include/fmt/format-inl.h | 16 +-
include/fmt/format.h | 715 +++++++++++++-----------------
include/fmt/os.h | 28 +-
include/fmt/ostream.h | 12 +-
include/fmt/printf.h | 6 +-
include/fmt/ranges.h | 120 +++--
include/fmt/std.h | 16 +-
include/fmt/xchar.h | 35 +-
src/format.cc | 1 +
src/os.cc | 2 +-
support/{manage.py => release.py} | 90 ++--
test/CMakeLists.txt | 3 +-
test/args-test.cc | 14 +
test/base-test.cc | 43 +-
test/compile-test.cc | 23 +-
test/format-impl-test.cc | 4 +-
test/format-test.cc | 25 +-
test/no-builtin-types-test.cc | 24 +
test/ranges-test.cc | 14 +-
test/scan.h | 4 +-
test/std-test.cc | 3 +
test/test-assert.h | 2 +-
test/xchar-test.cc | 27 +-
41 files changed, 1068 insertions(+), 774 deletions(-)
rename support/{manage.py => release.py} (69%)
create mode 100644 test/no-builtin-types-test.cc
diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml
index 88144dd9..50182ee9 100644
--- a/.github/workflows/cifuzz.yml
+++ b/.github/workflows/cifuzz.yml
@@ -10,18 +10,20 @@ jobs:
steps:
- name: Build fuzzers
id: build
- uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@92182553173581f871130c71c71b17f003d47b0a # master
+ uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@92182553173581f871130c71c71b17f003d47b0a
with:
oss-fuzz-project-name: 'fmt'
dry-run: false
language: c++
+
- name: Run fuzzers
- uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@92182553173581f871130c71c71b17f003d47b0a # master
+ uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@92182553173581f871130c71c71b17f003d47b0a
with:
oss-fuzz-project-name: 'fmt'
fuzz-seconds: 300
dry-run: false
language: c++
+
- name: Upload crash
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
if: failure() && steps.build.outcome == 'success'
diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml
index 3098d458..019a85f1 100644
--- a/.github/workflows/doc.yml
+++ b/.github/workflows/doc.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Add Ubuntu mirrors
run: |
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 51a62f46..cbef56a4 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -13,14 +13,16 @@ jobs:
format_code:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Install clang-format
- uses: aminya/setup-cpp@290824452986e378826155f3379d31bce8753d76 # v0.37.0
- with:
- clangformat: 17.0.5
+ run: |
+ wget https://apt.llvm.org/llvm.sh
+ sudo bash ./llvm.sh 17
+ sudo apt install clang-format-17
- name: Run clang-format
run: |
- find include src -name '*.h' -o -name '*.cc' | xargs clang-format -i -style=file -fallback-style=none
+ find include src -name '*.h' -o -name '*.cc' | \
+ xargs clang-format-17 -i -style=file -fallback-style=none
git diff --exit-code
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index b57814b4..97150467 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -62,7 +62,7 @@ jobs:
shared: -DBUILD_SHARED_LIBS=ON
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Set timezone
run: sudo timedatectl set-timezone 'Asia/Yekaterinburg'
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 5713c3e8..3543ef57 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -25,7 +25,7 @@ jobs:
runs-on: '${{ matrix.os }}'
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Set timezone
run: sudo systemsetup -settimezone 'Asia/Yekaterinburg'
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index 9d38f77e..b363a6f8 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -29,7 +29,7 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
with:
persist-credentials: false
@@ -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@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
+ uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
with:
sarif_file: results.sarif
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 79ca1814..5403e652 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -36,7 +36,7 @@ jobs:
standard: 20
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Set timezone
run: tzutil /s "Ekaterinburg Standard Time"
@@ -78,12 +78,12 @@ jobs:
- name: Set timezone
run: tzutil /s "Ekaterinburg Standard Time"
shell: cmd
- - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # v2.24.0
+ - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # v2.25.0
with:
release: false
msystem: ${{matrix.sys}}
pacboy: cc:p cmake:p ninja:p lld:p
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Configure
run: cmake -B ../build -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Debug
env: { LDFLAGS: -fuse-ld=lld }
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1606e886..586ead51 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -426,7 +426,9 @@ if (FMT_INSTALL)
endif()
# Install the library and headers.
- install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
+ install(TARGETS ${INSTALL_TARGETS}
+ COMPONENT core
+ EXPORT ${targets_export_name}
LIBRARY DESTINATION ${FMT_LIB_DIR}
ARCHIVE DESTINATION ${FMT_LIB_DIR}
PUBLIC_HEADER DESTINATION "${FMT_INC_DIR}/fmt"
@@ -439,13 +441,15 @@ if (FMT_INSTALL)
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
# Install version, config and target files.
- install(
- FILES ${project_config} ${version_config}
- DESTINATION ${FMT_CMAKE_DIR})
+ install(FILES ${project_config} ${version_config}
+ DESTINATION ${FMT_CMAKE_DIR}
+ COMPONENT core)
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR}
- NAMESPACE fmt::)
+ NAMESPACE fmt::
+ COMPONENT core)
- install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
+ install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}"
+ COMPONENT core)
endif ()
function(add_doc_target)
@@ -481,7 +485,8 @@ function(add_doc_target)
include(GNUInstallDirs)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/
- DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt OPTIONAL)
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt
+ COMPONENT doc OPTIONAL)
endfunction()
if (FMT_DOC)
diff --git a/ChangeLog.md b/ChangeLog.md
index 0eb9ba8e..09ebaed6 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,237 @@
-# 11.1.0 - TBD
+# 11.1.1 - 2024-12-27
-- Improved debug codegen.
+- Fixed ABI compatibility with earlier 11.x versions
+ (https://github.com/fmtlib/fmt/issues/4278).
+
+- Defined CMake components (`core` and `doc`) to allow docs to be installed
+ separately (https://github.com/fmtlib/fmt/pull/4276).
+ Thanks @carlsmedstad.
+
+# 11.1.0 - 2024-12-25
+
+- Improved C++20 module support
+ (https://github.com/fmtlib/fmt/issues/4081,
+ https://github.com/fmtlib/fmt/pull/4083,
+ https://github.com/fmtlib/fmt/pull/4084,
+ https://github.com/fmtlib/fmt/pull/4152,
+ https://github.com/fmtlib/fmt/issues/4153,
+ https://github.com/fmtlib/fmt/pull/4169,
+ https://github.com/fmtlib/fmt/issues/4190,
+ https://github.com/fmtlib/fmt/issues/4234,
+ https://github.com/fmtlib/fmt/pull/4239).
+ Thanks @kamrann and @Arghnews.
+
+- Reduced debug (unoptimized) binary code size and the number of template
+ instantiations when passing formatting arguments. For example, unoptimized
+ binary code size for `fmt::print("{}", 42)` was reduced by ~40% on GCC and
+ ~60% on clang (x86-64).
+
+ GCC:
+ - Before: 161 instructions of which 105 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/s9bGoo4ze)).
+ - After: 116 instructions of which 60 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/r7GGGxMs6)).
+
+ Clang:
+ - Before: 310 instructions of which 251 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/Ts88b7M9o)).
+ - After: 194 instructions of which 135 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/vcrjP8ceW)).
+
+- Added an experimental `fmt::writer` API that can be used for writing to
+ different destinations such as files or strings
+ (https://github.com/fmtlib/fmt/issues/2354).
+ For example ([godbolt](https://www.godbolt.org/z/rWoKfbP7e)):
+
+ ```c++
+ #include
+
+ void write_text(fmt::writer w) {
+ w.print("The answer is {}.", 42);
+ }
+
+ int main() {
+ // Write to FILE.
+ write_text(stdout);
+
+ // Write to fmt::ostream.
+ auto f = fmt::output_file("myfile");
+ write_text(f);
+
+ // Write to std::string.
+ auto sb = fmt::string_buffer();
+ write_text(sb);
+ std::string s = sb.str();
+ }
+ ```
+
+- Added width and alignment support to the formatter of `std::error_code`.
+
+- Made `std::expected` formattable
+ (https://github.com/fmtlib/fmt/issues/4145,
+ https://github.com/fmtlib/fmt/pull/4148).
+ For example ([godbolt](https://www.godbolt.org/z/hrj5c6G86)):
+
+ ```c++
+ fmt::print("{}", std::expected());
+ ```
+
+ prints
+
+ ```
+ expected()
+ ```
+
+ Thanks @phprus.
+
+- Made `fmt::is_formattable` SFINAE-friendly
+ (https://github.com/fmtlib/fmt/issues/4147).
+
+- Added support for `_BitInt` formatting when using clang
+ (https://github.com/fmtlib/fmt/issues/4007,
+ https://github.com/fmtlib/fmt/pull/4072,
+ https://github.com/fmtlib/fmt/issues/4140,
+ https://github.com/fmtlib/fmt/issues/4173,
+ https://github.com/fmtlib/fmt/pull/4176).
+ For example ([godbolt](https://www.godbolt.org/z/KWjbWec5z)):
+
+ ```c++
+ using int42 = _BitInt(42);
+ fmt::print("{}", int42(100));
+ ```
+
+ Thanks @Arghnews.
+
+- Added the `n` specifier for tuples and pairs
+ (https://github.com/fmtlib/fmt/pull/4107). Thanks @someonewithpc.
+
+- Added support for tuple-like types to `fmt::join`
+ (https://github.com/fmtlib/fmt/issues/4226,
+ https://github.com/fmtlib/fmt/pull/4230). Thanks @phprus.
+
+- Made more types formattable at compile time
+ (https://github.com/fmtlib/fmt/pull/4127). Thanks @AnthonyVH.
+
+- Implemented a more efficient compile-time `fmt::formatted_size`
+ (https://github.com/fmtlib/fmt/issues/4102,
+ https://github.com/fmtlib/fmt/pull/4103). Thanks @phprus.
+
+- Fixed compile-time formatting of some string types
+ (https://github.com/fmtlib/fmt/pull/4065). Thanks @torshepherd.
+
+- Made compiled version of `fmt::format_to` work with
+ `std::back_insert_iterator>`
+ (https://github.com/fmtlib/fmt/issues/4206,
+ https://github.com/fmtlib/fmt/pull/4211). Thanks @phprus.
+
+- Added a formatter for `std::reference_wrapper`
+ (https://github.com/fmtlib/fmt/pull/4163,
+ https://github.com/fmtlib/fmt/pull/4164). Thanks @yfeldblum and @phprus.
+
+- Added experimental padding support (glibc `strftime` extension) to `%m`, `%j`
+ and `%Y` (https://github.com/fmtlib/fmt/pull/4161). Thanks @KKhanhH.
+
+- Made microseconds formatted as `us` instead of `µs` if the Unicode support is
+ disabled (https://github.com/fmtlib/fmt/issues/4088).
+
+- Fixed an unreleased regression in transcoding of surrogate pairs
+ (https://github.com/fmtlib/fmt/issues/4094,
+ https://github.com/fmtlib/fmt/pull/4095). Thanks @phprus.
+
+- Made `fmt::appender` satisfy `std::output_iterator` concept
+ (https://github.com/fmtlib/fmt/issues/4092,
+ https://github.com/fmtlib/fmt/pull/4093). Thanks @phprus.
+
+- Made `std::iterator_traits` standard-conforming
+ (https://github.com/fmtlib/fmt/pull/4185). Thanks @CaseyCarter.
+
+- Made it easier to reuse `fmt::formatter` for types with
+ an implicit conversion to `std::string_view`
+ (https://github.com/fmtlib/fmt/issues/4036,
+ https://github.com/fmtlib/fmt/pull/4055). Thanks @Arghnews.
+
+- Made it possible to disable `` use via `FMT_CPP_LIB_FILESYSTEM`
+ for compatibility with some video game console SDKs, e.g. Nintendo Switch SDK
+ (https://github.com/fmtlib/fmt/issues/4257,
+ https://github.com/fmtlib/fmt/pull/4258,
+ https://github.com/fmtlib/fmt/pull/4259). Thanks @W4RH4WK and @phprus.
+
+- Fixed compatibility with platforms that use 80-bit `long double`
+ (https://github.com/fmtlib/fmt/issues/4245,
+ https://github.com/fmtlib/fmt/pull/4246). Thanks @jsirpoma.
+
+- Added support for UTF-32 code units greater than `0xFFFF` in fill
+ (https://github.com/fmtlib/fmt/issues/4201).
+
+- Fixed handling of legacy encodings on Windows with GCC
+ (https://github.com/fmtlib/fmt/issues/4162).
+
+- Made `fmt::to_string` take `fmt::basic_memory_buffer` by const reference
+ (https://github.com/fmtlib/fmt/issues/4261,
+ https://github.com/fmtlib/fmt/pull/4262). Thanks @sascha-devel.
+
+- Added `fmt::dynamic_format_arg_store::size`
+ (https://github.com/fmtlib/fmt/pull/4270). Thanks @hannes-harnisch.
+
+- Removed the ability to control locale usage via an undocumented
+ `FMT_STATIC_THOUSANDS_SEPARATOR` in favor of `FMT_USE_LOCALE`.
+
+- Renamed `FMT_EXCEPTIONS` to `FMT_USE_EXCEPTIONS` for consistency with other
+ similar macros.
+
+- Improved include directory ordering to reduce the chance of including
+ incorrect headers when using multiple versions of {fmt}
+ (https://github.com/fmtlib/fmt/pull/4116). Thanks @cdzhan.
+
+- Made it possible to compile a subset of {fmt} without the C++ runtime.
+
+- Improved documentation and README
+ (https://github.com/fmtlib/fmt/pull/4066,
+ https://github.com/fmtlib/fmt/issues/4117,
+ https://github.com/fmtlib/fmt/issues/4203,
+ https://github.com/fmtlib/fmt/pull/4235). Thanks @zyctree and @nikola-sh.
+
+- Improved the documentation generator (https://github.com/fmtlib/fmt/pull/4110,
+ https://github.com/fmtlib/fmt/pull/4115). Thanks @rturrado.
+
+- Improved CI (https://github.com/fmtlib/fmt/pull/4155,
+ https://github.com/fmtlib/fmt/pull/4151). Thanks @phprus.
+
+- Fixed various warnings and compilation issues
+ (https://github.com/fmtlib/fmt/issues/2708,
+ https://github.com/fmtlib/fmt/issues/4091,
+ https://github.com/fmtlib/fmt/issues/4109,
+ https://github.com/fmtlib/fmt/issues/4113,
+ https://github.com/fmtlib/fmt/issues/4125,
+ https://github.com/fmtlib/fmt/issues/4129,
+ https://github.com/fmtlib/fmt/pull/4130,
+ https://github.com/fmtlib/fmt/pull/4131,
+ https://github.com/fmtlib/fmt/pull/4132,
+ https://github.com/fmtlib/fmt/issues/4133,
+ https://github.com/fmtlib/fmt/issues/4144,
+ https://github.com/fmtlib/fmt/issues/4150,
+ https://github.com/fmtlib/fmt/issues/4158,
+ https://github.com/fmtlib/fmt/pull/4159,
+ https://github.com/fmtlib/fmt/issues/4160,
+ https://github.com/fmtlib/fmt/pull/4170,
+ https://github.com/fmtlib/fmt/issues/4177,
+ https://github.com/fmtlib/fmt/pull/4187,
+ https://github.com/fmtlib/fmt/pull/4188,
+ https://github.com/fmtlib/fmt/pull/4194,
+ https://github.com/fmtlib/fmt/pull/4200,
+ https://github.com/fmtlib/fmt/issues/4205,
+ https://github.com/fmtlib/fmt/issues/4207,
+ https://github.com/fmtlib/fmt/pull/4208,
+ https://github.com/fmtlib/fmt/pull/4210,
+ https://github.com/fmtlib/fmt/issues/4220,
+ https://github.com/fmtlib/fmt/issues/4231,
+ https://github.com/fmtlib/fmt/issues/4232,
+ https://github.com/fmtlib/fmt/pull/4233,
+ https://github.com/fmtlib/fmt/pull/4236,
+ https://github.com/fmtlib/fmt/pull/4267,
+ https://github.com/fmtlib/fmt/pull/4271).
+ Thanks @torsten48, @Arghnews, @tinfoilboy, @aminya, @Ottani, @zeroomega,
+ @c4v4, @kongy, @vinayyadav3016, @sergio-nsk, @phprus and @YexuanXiao.
# 11.0.2 - 2024-07-20
@@ -272,6 +503,9 @@
- Fixed handling of negative ids in `fmt::basic_format_args::get`
(https://github.com/fmtlib/fmt/pull/3945). Thanks @marlenecota.
+- Fixed handling of a buffer boundary on flush
+ (https://github.com/fmtlib/fmt/issues/4229).
+
- Improved named argument validation
(https://github.com/fmtlib/fmt/issues/3817).
diff --git a/README.md b/README.md
index 5f9249d4..fd845db2 100644
--- a/README.md
+++ b/README.md
@@ -291,6 +291,7 @@ converts to `std::print`.)
- [ccache](https://ccache.dev/): a compiler cache
- [ClickHouse](https://github.com/ClickHouse/ClickHouse): an
analytical database management system
+- [ContextVision](https://www.contextvision.com/): medical imaging software
- [Contour](https://github.com/contour-terminal/contour/): a modern
terminal emulator
- [CUAUV](https://cuauv.org/): Cornell University\'s autonomous
diff --git a/doc/api.md b/doc/api.md
index bf0df731..e86f0b06 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -269,18 +269,16 @@ that support C++20 `consteval`. On older compilers you can use the
Unused arguments are allowed as in Python's `str.format` and ordinary functions.
-::: basic_format_string
+See [Type Erasure](#type-erasure) for an example of how to enable compile-time
+checks in your own functions with `fmt::format_string` while avoiding template
+bloat.
+
+::: fstring
::: format_string
::: runtime(string_view)
-### Named Arguments
-
-::: arg(const Char*, const T&)
-
-Named arguments are not supported in compile-time checks at the moment.
-
### Type Erasure
You can create your own formatting function with compile-time checks and
@@ -317,6 +315,12 @@ parameterized version.
::: basic_format_arg
+### Named Arguments
+
+::: arg(const Char*, const T&)
+
+Named arguments are not supported in compile-time checks at the moment.
+
### Compatibility
::: basic_string_view
@@ -375,18 +379,17 @@ allocator:
using custom_string =
std::basic_string, custom_allocator>;
- custom_string vformat(custom_allocator alloc, fmt::string_view format_str,
- fmt::format_args args) {
+ auto vformat(custom_allocator alloc, fmt::string_view fmt,
+ fmt::format_args args) -> custom_string {
auto buf = custom_memory_buffer(alloc);
- fmt::vformat_to(std::back_inserter(buf), format_str, args);
+ fmt::vformat_to(std::back_inserter(buf), fmt, args);
return custom_string(buf.data(), buf.size(), alloc);
}
template
- inline custom_string format(custom_allocator alloc,
- fmt::string_view format_str,
- const Args& ... args) {
- return vformat(alloc, format_str, fmt::make_format_args(args...));
+ auto format(custom_allocator alloc, fmt::string_view fmt,
+ const Args& ... args) -> custom_string {
+ return vformat(alloc, fmt, fmt::make_format_args(args...));
}
The allocator will be used for the output container only. Formatting
@@ -410,11 +413,11 @@ locale:
that take `std::locale` as a parameter. The locale type is a template
parameter to avoid the expensive `` include.
-::: format(const Locale&, format_string, T&&...)
+::: format(detail::locale_ref, format_string, T&&...)
-::: format_to(OutputIt, const Locale&, format_string, T&&...)
+::: format_to(OutputIt, detail::locale_ref, format_string, T&&...)
-::: formatted_size(const Locale&, format_string, T&&...)
+::: formatted_size(detail::locale_ref, format_string, T&&...)
### Legacy Compile-Time Checks
@@ -498,10 +501,13 @@ chrono-format-specifications).
- [`std::atomic_flag`](https://en.cppreference.com/w/cpp/atomic/atomic_flag)
- [`std::bitset`](https://en.cppreference.com/w/cpp/utility/bitset)
- [`std::error_code`](https://en.cppreference.com/w/cpp/error/error_code)
+- [`std::exception`](https://en.cppreference.com/w/cpp/error/exception)
- [`std::filesystem::path`](https://en.cppreference.com/w/cpp/filesystem/path)
-- [`std::monostate`](https://en.cppreference.com/w/cpp/utility/variant/monostate)
+- [`std::monostate`](
+ https://en.cppreference.com/w/cpp/utility/variant/monostate)
- [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional)
-- [`std::source_location`](https://en.cppreference.com/w/cpp/utility/source_location)
+- [`std::source_location`](
+ https://en.cppreference.com/w/cpp/utility/source_location)
- [`std::thread::id`](https://en.cppreference.com/w/cpp/thread/thread/id)
- [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant/variant)
@@ -509,7 +515,7 @@ chrono-format-specifications).
::: ptr(const std::shared_ptr&)
-### Formatting Variants
+### Variants
A `std::variant` is only formattable if every variant alternative is
formattable, and requires the `__cpp_lib_variant` [library
@@ -525,15 +531,32 @@ feature](https://en.cppreference.com/w/cpp/feature_test).
fmt::print("{}", std::variant());
// Output: variant(monostate)
+## Bit-Fields and Packed Structs
+
+To format a bit-field or a field of a struct with `__attribute__((packed))`
+applied to it, you need to convert it to the underlying or compatible type via
+a cast or a unary `+` ([godbolt](https://www.godbolt.org/z/3qKKs6T5Y)):
+
+```c++
+struct smol {
+ int bit : 1;
+};
+
+auto s = smol();
+fmt::print("{}", +s.bit);
+```
+
+This is a known limitation of "perfect" forwarding in C++.
+
## Format String Compilation
-`fmt/compile.h` provides format string compilation enabled via the
-`FMT_COMPILE` macro or the `_cf` user-defined literal defined in
-namespace `fmt::literals`. Format strings marked with `FMT_COMPILE`
-or `_cf` are parsed, checked and converted into efficient formatting
-code at compile-time. This supports arguments of built-in and string
-types as well as user-defined types with `format` functions taking
+`fmt/compile.h` provides format string compilation and compile-time
+(`constexpr`) formatting enabled via the `FMT_COMPILE` macro or the `_cf`
+user-defined literal defined in namespace `fmt::literals`. Format strings
+marked with `FMT_COMPILE` or `_cf` are parsed, checked and converted into
+efficient formatting code at compile-time. This supports arguments of built-in
+and string types as well as user-defined types with `format` functions taking
the format context type as a template parameter in their `formatter`
specializations. For example:
diff --git a/doc/get-started.md b/doc/get-started.md
index e61da882..466d1c1b 100644
--- a/doc/get-started.md
+++ b/doc/get-started.md
@@ -202,7 +202,7 @@ For a static build, use the following subproject definition:
For the header-only version, use:
- fmt = subproject('fmt')
+ fmt = subproject('fmt', default_options: ['header-only=true'])
fmt_dep = fmt.get_variable('fmt_header_only_dep')
### Android NDK
diff --git a/doc/index.md b/doc/index.md
index b170f9f2..4f28e114 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -122,8 +122,8 @@ hide:
The library is highly portable and requires only a minimal subset of
- C++11 features which are available in GCC 4.9, Clang 3.4, MSVC 19.0
- (2015) and later. Newer compiler and standard library features are used
+ C++11 features which are available in GCC 4.9, Clang 3.4, MSVC 19.10
+ (2017) and later. Newer compiler and standard library features are used
if available, and enable additional functionality.
diff --git a/doc/syntax.md b/doc/syntax.md
index 1a44e867..46d7d2fd 100644
--- a/doc/syntax.md
+++ b/doc/syntax.md
@@ -706,12 +706,12 @@ The available padding modifiers (*padding_modifier*) are:
| Type | Meaning |
|-------|-----------------------------------------|
-| `'-'` | Pad a numeric result with spaces. |
-| `'_'` | Do not pad a numeric result string. |
+| `'_'` | Pad a numeric result with spaces. |
+| `'-'` | Do not pad a numeric result string. |
| `'0'` | Pad a numeric result string with zeros. |
These modifiers are only supported for the `'H'`, `'I'`, `'M'`, `'S'`, `'U'`,
-`'V'`, `'W'`, `'m'`, `'j'`, `'Y'` presentation types.
+`'V'`, `'W'`, `'Y'`, `'d'`, `'j'` and `'m'` presentation types.
## Range Format Specifications
diff --git a/include/fmt/args.h b/include/fmt/args.h
index 6ed30c0b..3ff47880 100644
--- a/include/fmt/args.h
+++ b/include/fmt/args.h
@@ -210,6 +210,9 @@ template class dynamic_format_arg_store {
data_.reserve(new_cap);
named_info_.reserve(new_cap_named);
}
+
+ /// Returns the number of elements in the store.
+ size_t size() const noexcept { return data_.size(); }
};
FMT_END_NAMESPACE
diff --git a/include/fmt/base.h b/include/fmt/base.h
index b36faabc..a6948d40 100644
--- a/include/fmt/base.h
+++ b/include/fmt/base.h
@@ -21,7 +21,7 @@
#endif
// The fmt library version in the form major * 10000 + minor * 100 + patch.
-#define FMT_VERSION 110002
+#define FMT_VERSION 110101
// Detect compiler versions.
#if defined(__clang__) && !defined(__ibmxl__)
@@ -146,6 +146,8 @@
// Use the provided definition.
#elif defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_USE_EXCEPTIONS 0
+#elif defined(__clang__) && !defined(__cpp_exceptions)
+# define FMT_USE_EXCEPTIONS 0
#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS
# define FMT_USE_EXCEPTIONS 0
#else
@@ -159,6 +161,20 @@
# define FMT_CATCH(x) if (false)
#endif
+#ifdef FMT_NO_UNIQUE_ADDRESS
+// Use the provided definition.
+#elif FMT_CPLUSPLUS < 202002L
+// Not supported.
+#elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
+# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
+// 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
+#ifndef FMT_NO_UNIQUE_ADDRESS
+# define FMT_NO_UNIQUE_ADDRESS
+#endif
+
#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
# define FMT_FALLTHROUGH [[fallthrough]]
#elif defined(__clang__)
@@ -332,6 +348,13 @@ struct monostate {
# define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0
#endif
+template constexpr auto min_of(T a, T b) -> T {
+ return a < b ? a : b;
+}
+template constexpr auto max_of(T a, T b) -> T {
+ return a > b ? a : b;
+}
+
namespace detail {
// Suppresses "unused variable" warnings with the method described in
// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
@@ -355,7 +378,9 @@ constexpr auto is_constant_evaluated(bool default_value = false) noexcept
}
// Suppresses "conditional expression is constant" warnings.
-template constexpr auto const_check(T value) -> T { return value; }
+template FMT_ALWAYS_INLINE constexpr auto const_check(T val) -> T {
+ return val;
+}
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
const char* message);
@@ -394,7 +419,7 @@ inline auto map(uint128_opt) -> monostate { return {}; }
#endif
#ifndef FMT_USE_BITINT
-# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1400)
+# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500)
#endif
#if FMT_USE_BITINT
@@ -562,8 +587,8 @@ template class basic_string_view {
// Lexicographically compare this string reference to other.
FMT_CONSTEXPR auto compare(basic_string_view other) const -> int {
- size_t str_size = size_ < other.size_ ? size_ : other.size_;
- int result = detail::compare(data_, other.data_, str_size);
+ int result =
+ detail::compare(data_, other.data_, min_of(size_, other.size_));
if (result != 0) return result;
return size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
}
@@ -714,7 +739,7 @@ class basic_specs {
max_fill_size = 4
};
- unsigned long data_ = 1 << fill_size_shift;
+ size_t data_ = 1 << fill_size_shift;
// Character (code unit) type is erased to prevent template bloat.
char fill_data_[max_fill_size] = {' '};
@@ -793,7 +818,8 @@ class basic_specs {
template constexpr auto fill_unit() const -> Char {
using uchar = unsigned char;
return static_cast(static_cast(fill_data_[0]) |
- (static_cast(fill_data_[1]) << 8));
+ (static_cast(fill_data_[1]) << 8) |
+ (static_cast(fill_data_[2]) << 16));
}
FMT_CONSTEXPR void set_fill(char c) {
@@ -809,12 +835,19 @@ class basic_specs {
unsigned uchar = static_cast>(s[0]);
fill_data_[0] = static_cast(uchar);
fill_data_[1] = static_cast(uchar >> 8);
+ fill_data_[2] = static_cast(uchar >> 16);
return;
}
FMT_ASSERT(size <= max_fill_size, "invalid fill");
for (size_t i = 0; i < size; ++i)
fill_data_[i & 3] = static_cast(s[i]);
}
+
+ FMT_CONSTEXPR void set_fill(const basic_specs& specs) {
+ set_fill_size(specs.fill_size());
+ for (size_t i = 0; i < max_fill_size; ++i)
+ fill_data_[i] = specs.fill_data_[i];
+ }
};
// Format specifiers for built-in and string types.
@@ -842,7 +875,7 @@ template class parse_context {
using char_type = Char;
using iterator = const Char*;
- explicit constexpr parse_context(basic_string_view fmt,
+ constexpr explicit parse_context(basic_string_view fmt,
int next_arg_id = 0)
: fmt_(fmt), next_arg_id_(next_arg_id) {}
@@ -1012,15 +1045,15 @@ template struct named_arg : view {
static_assert(!is_named_arg::value, "nested named arguments");
};
-template constexpr auto count() -> size_t { return B ? 1 : 0; }
-template constexpr auto count() -> size_t {
+template constexpr auto count() -> int { return B ? 1 : 0; }
+template constexpr auto count() -> int {
return (B1 ? 1 : 0) + count();
}
-template constexpr auto count_named_args() -> size_t {
+template constexpr auto count_named_args() -> int {
return count::value...>();
}
-template constexpr auto count_static_named_args() -> size_t {
+template constexpr auto count_static_named_args() -> int {
return count::value...>();
}
@@ -1180,7 +1213,7 @@ class compile_parse_context : public parse_context {
using base = parse_context;
public:
- explicit FMT_CONSTEXPR compile_parse_context(basic_string_view fmt,
+ FMT_CONSTEXPR explicit compile_parse_context(basic_string_view fmt,
int num_args, const type* types,
int next_arg_id = 0)
: base(fmt, next_arg_id), num_args_(num_args), types_(types) {}
@@ -1627,16 +1660,16 @@ template struct arg_pack {};
template
class format_string_checker {
private:
- type types_[NUM_ARGS > 0 ? NUM_ARGS : 1];
- named_arg_info named_args_[NUM_NAMED_ARGS > 0 ? NUM_NAMED_ARGS : 1];
+ type types_[max_of(1, NUM_ARGS)];
+ named_arg_info named_args_[max_of(1, NUM_NAMED_ARGS)];
compile_parse_context context_;
using parse_func = auto (*)(parse_context&) -> const Char*;
- parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1];
+ parse_func parse_funcs_[max_of(1, NUM_ARGS)];
public:
template
- explicit FMT_CONSTEXPR format_string_checker(basic_string_view fmt,
+ FMT_CONSTEXPR explicit format_string_checker(basic_string_view fmt,
arg_pack)
: types_{mapped_type_constant::value...},
named_args_{},
@@ -1694,7 +1727,7 @@ template class buffer {
protected:
// Don't initialize ptr_ since it is not accessed to save a few cycles.
FMT_MSC_WARNING(suppress : 26495)
- FMT_CONSTEXPR20 buffer(grow_fun grow, size_t sz) noexcept
+ FMT_CONSTEXPR buffer(grow_fun grow, size_t sz) noexcept
: size_(sz), capacity_(sz), grow_(grow) {}
constexpr buffer(grow_fun grow, T* p = nullptr, size_t sz = 0,
@@ -1740,7 +1773,7 @@ template class buffer {
// the new elements may not be initialized.
FMT_CONSTEXPR void try_resize(size_t count) {
try_reserve(count);
- size_ = count <= capacity_ ? count : capacity_;
+ size_ = min_of(count, capacity_);
}
// Tries increasing the buffer capacity to `new_capacity`. It can increase the
@@ -1788,9 +1821,9 @@ template class buffer {
};
struct buffer_traits {
- explicit buffer_traits(size_t) {}
- auto count() const -> size_t { return 0; }
- auto limit(size_t size) -> size_t { return size; }
+ constexpr explicit buffer_traits(size_t) {}
+ constexpr auto count() const -> size_t { return 0; }
+ constexpr auto limit(size_t size) const -> size_t { return size; }
};
class fixed_buffer_traits {
@@ -1799,12 +1832,12 @@ class fixed_buffer_traits {
size_t limit_;
public:
- explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
- auto count() const -> size_t { return count_; }
- auto limit(size_t size) -> size_t {
+ constexpr explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
+ constexpr auto count() const -> size_t { return count_; }
+ FMT_CONSTEXPR auto limit(size_t size) -> size_t {
size_t n = limit_ > count_ ? limit_ - count_ : 0;
count_ += size;
- return size < n ? size : n;
+ return min_of(size, n);
}
};
@@ -1962,15 +1995,37 @@ template class counting_buffer : public buffer {
template
struct is_back_insert_iterator> : std::true_type {};
+template
+struct has_back_insert_iterator_container_append : std::false_type {};
+template
+struct has_back_insert_iterator_container_append<
+ OutputIt, InputIt,
+ void_t())
+ .append(std::declval(),
+ std::declval()))>> : std::true_type {};
+
// An optimized version of std::copy with the output value type (T).
template ::value)>
+ FMT_ENABLE_IF(is_back_insert_iterator::value&&
+ has_back_insert_iterator_container_append<
+ OutputIt, InputIt>::value)>
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
-> OutputIt {
get_container(out).append(begin, end);
return out;
}
+template ::value &&
+ !has_back_insert_iterator_container_append<
+ OutputIt, InputIt>::value)>
+FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
+ -> OutputIt {
+ auto& c = get_container(out);
+ c.insert(c.end(), begin, end);
+ return out;
+}
+
template ::value)>
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
@@ -2146,7 +2201,8 @@ template class value {
template ::value)>
value(const T& named_arg) : value(named_arg.value) {}
- template ::value)>
+ template ::value || !FMT_BUILTIN_TYPES)>
FMT_CONSTEXPR20 FMT_INLINE value(T& x) : value(x, custom_tag()) {}
FMT_ALWAYS_INLINE value(const named_arg_info* args, size_t size)
@@ -2220,9 +2276,12 @@ struct locale_ref {
public:
constexpr locale_ref() : locale_(nullptr) {}
- template explicit locale_ref(const Locale& loc);
- explicit operator bool() const noexcept { return locale_ != nullptr; }
-#endif
+
+ template
+ locale_ref(const Locale& loc);
+
+ inline explicit operator bool() const noexcept { return locale_ != nullptr; }
+#endif // FMT_USE_LOCALE
template auto get() const -> Locale;
};
@@ -2243,16 +2302,15 @@ constexpr auto make_descriptor() -> unsigned long long {
: is_unpacked_bit | NUM_ARGS;
}
-template
+template
using arg_t = conditional_t,
basic_format_arg>;
-template
struct named_arg_store {
// args_[0].named_args points to named_args to avoid bloating format_args.
- // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
- arg_t args[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
+ arg_t args[1 + NUM_ARGS];
named_arg_info named_args[NUM_NAMED_ARGS];
template
@@ -2280,13 +2338,13 @@ struct named_arg_store {
// An array of references to arguments. It can be implicitly converted to
// `basic_format_args` for passing into type-erased formatting functions
// such as `vformat`. It is a plain struct to reduce binary size in debug mode.
-template
struct format_arg_store {
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
using type =
conditional_t[NUM_ARGS != 0 ? NUM_ARGS : +1],
+ arg_t[max_of(1, NUM_ARGS)],
named_arg_store>;
type args;
};
@@ -2372,11 +2430,6 @@ template class basic_appender {
detail::buffer* container;
public:
- using iterator_category = int;
- using value_type = T;
- using pointer = T*;
- using reference = T&;
- using difference_type = decltype(pointer() - pointer());
using container_type = detail::buffer;
FMT_CONSTEXPR basic_appender(detail::buffer& buf) : container(&buf) {}
@@ -2503,7 +2556,7 @@ template class basic_format_args {
return static_cast((desc_ >> shift) & mask);
}
- template
+ template
using store =
detail::format_arg_store;
@@ -2513,14 +2566,14 @@ template class basic_format_args {
constexpr basic_format_args() : desc_(0), args_(nullptr) {}
/// Constructs a `basic_format_args` object from `format_arg_store`.
- template
constexpr FMT_ALWAYS_INLINE basic_format_args(
const store& s)
: desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)),
values_(s.args) {}
- template detail::max_packed_args)>
constexpr basic_format_args(const store& s)
: desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)),
@@ -2571,10 +2624,11 @@ template class basic_format_args {
};
// A formatting context.
-class context : private detail::locale_ref {
+class context {
private:
appender out_;
format_args args_;
+ FMT_NO_UNIQUE_ADDRESS detail::locale_ref loc_;
public:
/// The character type for the output.
@@ -2590,24 +2644,26 @@ class context : private detail::locale_ref {
/// in the object so make sure they have appropriate lifetimes.
FMT_CONSTEXPR context(iterator out, format_args args,
detail::locale_ref loc = {})
- : locale_ref(loc), out_(out), args_(args) {}
+ : out_(out), args_(args), loc_(loc) {}
context(context&&) = default;
context(const context&) = delete;
void operator=(const context&) = delete;
FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); }
- auto arg(string_view name) -> format_arg { return args_.get(name); }
- FMT_CONSTEXPR auto arg_id(string_view name) -> int {
+ inline auto arg(string_view name) const -> format_arg {
+ return args_.get(name);
+ }
+ FMT_CONSTEXPR auto arg_id(string_view name) const -> int {
return args_.get_id(name);
}
// Returns an iterator to the beginning of the output range.
- FMT_CONSTEXPR auto out() -> iterator { return out_; }
+ FMT_CONSTEXPR auto out() const -> iterator { return out_; }
// Advances the begin iterator to `it`.
- void advance_to(iterator) {}
+ FMT_CONSTEXPR void advance_to(iterator) {}
- FMT_CONSTEXPR auto locale() -> detail::locale_ref { return *this; }
+ FMT_CONSTEXPR auto locale() const -> detail::locale_ref { return loc_; }
};
template struct runtime_format_string {
@@ -2624,7 +2680,8 @@ template struct runtime_format_string {
*/
inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
-/// A compile-time format string.
+/// A compile-time format string. Use `format_string` in the public API to
+/// prevent type deduction.
template struct fstring {
private:
static constexpr int num_static_named_args =
@@ -2657,8 +2714,9 @@ template struct fstring {
template ::value)>
FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
+ auto sv = string_view(str);
if (FMT_USE_CONSTEVAL)
- detail::parse_format_string(s, checker(s, arg_pack()));
+ detail::parse_format_string(sv, checker(sv, arg_pack()));
#ifdef FMT_ENFORCE_COMPILE_STRING
static_assert(
FMT_USE_CONSTEVAL && sizeof(s) != 0,
@@ -2711,8 +2769,8 @@ struct formatter(),
+ int NUM_ARGS = sizeof...(T),
+ int NUM_NAMED_ARGS = detail::count_named_args(),
unsigned long long DESC = detail::make_descriptor()>
constexpr FMT_ALWAYS_INLINE auto make_format_args(T&... args)
-> detail::format_arg_store {
@@ -2851,7 +2909,7 @@ FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args);
template
FMT_INLINE void print(format_string fmt, T&&... args) {
vargs va = {{args...}};
- if (!detail::use_utf8)
+ if (detail::const_check(!detail::use_utf8))
return detail::vprint_mojibake(stdout, fmt.str, va, false);
return detail::is_locking() ? vprint_buffered(stdout, fmt.str, va)
: vprint(fmt.str, va);
@@ -2868,7 +2926,8 @@ FMT_INLINE void print(format_string fmt, T&&... args) {
template
FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) {
vargs va = {{args...}};
- if (!detail::use_utf8) return detail::vprint_mojibake(f, fmt.str, va, false);
+ if (detail::const_check(!detail::use_utf8))
+ return detail::vprint_mojibake(f, fmt.str, va, false);
return detail::is_locking() ? vprint_buffered(f, fmt.str, va)
: vprint(f, fmt.str, va);
}
@@ -2878,8 +2937,9 @@ FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) {
template
FMT_INLINE void println(FILE* f, format_string fmt, T&&... args) {
vargs va = {{args...}};
- return detail::use_utf8 ? vprintln(f, fmt.str, va)
- : detail::vprint_mojibake(f, fmt.str, va, true);
+ return detail::const_check(detail::use_utf8)
+ ? vprintln(f, fmt.str, va)
+ : detail::vprint_mojibake(f, fmt.str, va, true);
}
/// Formats `args` according to specifications in `fmt` and writes the output
diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h
index 5472eae0..abf3671e 100644
--- a/include/fmt/chrono.h
+++ b/include/fmt/chrono.h
@@ -444,7 +444,7 @@ struct is_same_arithmetic_type
std::is_floating_point::value)> {
};
-inline void throw_duration_error() {
+FMT_NORETURN inline void throw_duration_error() {
FMT_THROW(format_error("cannot format duration"));
}
@@ -540,24 +540,24 @@ inline auto localtime(std::time_t time) -> std::tm {
std::time_t time_;
std::tm tm_;
- dispatcher(std::time_t t) : time_(t) {}
+ inline dispatcher(std::time_t t) : time_(t) {}
- auto run() -> bool {
+ inline auto run() -> bool {
using namespace fmt::detail;
return handle(localtime_r(&time_, &tm_));
}
- auto handle(std::tm* tm) -> bool { return tm != nullptr; }
+ inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
- auto handle(detail::null<>) -> bool {
+ inline auto handle(detail::null<>) -> bool {
using namespace fmt::detail;
return fallback(localtime_s(&tm_, &time_));
}
- auto fallback(int res) -> bool { return res == 0; }
+ inline auto fallback(int res) -> bool { return res == 0; }
#if !FMT_MSC_VERSION
- auto fallback(detail::null<>) -> bool {
+ inline auto fallback(detail::null<>) -> bool {
using namespace fmt::detail;
std::tm* tm = std::localtime(&time_);
if (tm) tm_ = *tm;
@@ -591,24 +591,24 @@ inline auto gmtime(std::time_t time) -> std::tm {
std::time_t time_;
std::tm tm_;
- dispatcher(std::time_t t) : time_(t) {}
+ inline dispatcher(std::time_t t) : time_(t) {}
- auto run() -> bool {
+ inline auto run() -> bool {
using namespace fmt::detail;
return handle(gmtime_r(&time_, &tm_));
}
- auto handle(std::tm* tm) -> bool { return tm != nullptr; }
+ inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
- auto handle(detail::null<>) -> bool {
+ inline auto handle(detail::null<>) -> bool {
using namespace fmt::detail;
return fallback(gmtime_s(&tm_, &time_));
}
- auto fallback(int res) -> bool { return res == 0; }
+ inline auto fallback(int res) -> bool { return res == 0; }
#if !FMT_MSC_VERSION
- auto fallback(detail::null<>) -> bool {
+ inline auto fallback(detail::null<>) -> bool {
std::tm* tm = std::gmtime(&time_);
if (tm) tm_ = *tm;
return tm != nullptr;
@@ -912,7 +912,9 @@ template struct null_chrono_spec_handler {
};
struct tm_format_checker : null_chrono_spec_handler {
- FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); }
+ FMT_NORETURN inline void unsupported() {
+ FMT_THROW(format_error("no format"));
+ }
template
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
@@ -1069,7 +1071,7 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) {
}
} else if (precision > 0) {
*out++ = '.';
- leading_zeroes = (std::min)(leading_zeroes, precision);
+ leading_zeroes = min_of(leading_zeroes, precision);
int remaining = precision - leading_zeroes;
out = detail::fill_n(out, leading_zeroes, '0');
if (remaining < num_digits) {
@@ -1572,7 +1574,7 @@ class tm_writer {
struct chrono_format_checker : null_chrono_spec_handler {
bool has_precision_integral = false;
- FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); }
+ FMT_NORETURN inline void unsupported() { FMT_THROW(format_error("no date")); }
template
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
@@ -1693,14 +1695,14 @@ class get_locale {
bool has_locale_ = false;
public:
- get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
+ inline get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
if (localized)
::new (&locale_) std::locale(loc.template get());
}
- ~get_locale() {
+ inline ~get_locale() {
if (has_locale_) locale_.~locale();
}
- operator const std::locale&() const {
+ inline operator const std::locale&() const {
return has_locale_ ? locale_ : get_classic_locale();
}
};
diff --git a/include/fmt/compile.h b/include/fmt/compile.h
index c33427ab..68b451c7 100644
--- a/include/fmt/compile.h
+++ b/include/fmt/compile.h
@@ -42,11 +42,10 @@ struct is_compiled_string : std::is_base_of {};
#endif
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
-template Str>
+template Str>
struct udl_compiled_string : compiled_string {
using char_type = Char;
- explicit constexpr operator basic_string_view() const {
+ constexpr explicit operator basic_string_view() const {
return {Str.data, N - 1};
}
};
@@ -525,9 +524,9 @@ FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args)
template ::value)>
void print(std::FILE* f, const S& fmt, const Args&... args) {
- memory_buffer buffer;
- fmt::format_to(std::back_inserter(buffer), fmt, args...);
- detail::print(f, {buffer.data(), buffer.size()});
+ auto buf = memory_buffer();
+ fmt::format_to(appender(buf), fmt, args...);
+ detail::print(f, {buf.data(), buf.size()});
}
template constexpr auto operator""_cf() {
+template constexpr auto operator""_cf() {
using char_t = remove_cvref_t;
return detail::udl_compiled_string();
diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h
index e4dd7ea8..14c65a09 100644
--- a/include/fmt/format-inl.h
+++ b/include/fmt/format-inl.h
@@ -26,6 +26,10 @@
# include
#endif
+#ifndef FMT_FUNC
+# define FMT_FUNC
+#endif
+
FMT_BEGIN_NAMESPACE
namespace detail {
@@ -59,8 +63,8 @@ FMT_FUNC void format_error_code(detail::buffer& out, int error_code,
FMT_ASSERT(out.size() <= inline_buffer_size, "");
}
-FMT_FUNC void report_error(format_func func, int error_code,
- const char* message) noexcept {
+FMT_FUNC void do_report_error(format_func func, int error_code,
+ const char* message) noexcept {
memory_buffer full_message;
func(full_message, error_code, message);
// Don't use fwrite_all because the latter may throw.
@@ -80,7 +84,7 @@ using std::locale;
using std::numpunct;
using std::use_facet;
-template
+template >
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
static_assert(std::is_same::value, "");
}
@@ -130,7 +134,9 @@ FMT_FUNC auto write_loc(appender out, loc_value value,
FMT_FUNC void report_error(const char* message) {
#if FMT_USE_EXCEPTIONS
- throw format_error(message);
+ // Use FMT_THROW instead of throw to avoid bogus unreachable code warnings
+ // from MSVC.
+ FMT_THROW(format_error(message));
#else
fputs(message, stderr);
abort();
@@ -1430,7 +1436,7 @@ FMT_FUNC void format_system_error(detail::buffer& out, int error_code,
FMT_FUNC void report_system_error(int error_code,
const char* message) noexcept {
- report_error(format_system_error, error_code, message);
+ do_report_error(format_system_error, error_code, message);
}
FMT_FUNC auto vformat(string_view fmt, format_args args) -> std::string {
diff --git a/include/fmt/format.h b/include/fmt/format.h
index 880d948b..c9a6054d 100644
--- a/include/fmt/format.h
+++ b/include/fmt/format.h
@@ -41,13 +41,12 @@
#include "base.h"
#ifndef FMT_MODULE
-# include // std::signbit
-# include // std::byte
-# include // uint32_t
-# include // std::memcpy
-# include // std::initializer_list
-# include // std::numeric_limits
-# include // std::bad_alloc
+# include // std::signbit
+# include // std::byte
+# include // uint32_t
+# include // std::memcpy
+# include // std::numeric_limits
+# include // std::bad_alloc
# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)
// Workaround for pre gcc 5 libstdc++.
# include // std::allocator_traits
@@ -56,7 +55,7 @@
# include // std::string
# include // std::system_error
-// Checking FMT_CPLUSPLUS for warning suppression in MSVC.
+// Check FMT_CPLUSPLUS to avoid a warning in MSVC.
# if FMT_HAS_INCLUDE() && FMT_CPLUSPLUS > 201703L
# include // std::bit_cast
# endif
@@ -69,7 +68,7 @@
# endif
# if FMT_MSC_VERSION
-# include // _BitScanReverse[64], _BitScanForward[64], _umul128
+# include // _BitScanReverse[64], _umul128
# endif
#endif // FMT_MODULE
@@ -119,11 +118,13 @@
#endif
namespace std {
-template <> struct iterator_traits {
+template struct iterator_traits> {
using iterator_category = output_iterator_tag;
- using value_type = char;
- using reference = char&;
- using difference_type = fmt::appender::difference_type;
+ using value_type = T;
+ using difference_type =
+ decltype(static_cast(nullptr) - static_cast(nullptr));
+ using pointer = void;
+ using reference = void;
};
} // namespace std
@@ -147,22 +148,8 @@ FMT_END_NAMESPACE
# else
# define FMT_THROW(x) \
::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
-# endif
-#endif
-
-#ifdef FMT_NO_UNIQUE_ADDRESS
-// Use the provided definition.
-#elif FMT_CPLUSPLUS < 202002L
-// Not supported.
-#elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
-# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
-// 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
-#ifndef FMT_NO_UNIQUE_ADDRESS
-# define FMT_NO_UNIQUE_ADDRESS
-#endif
+# endif // FMT_USE_EXCEPTIONS
+#endif // FMT_THROW
// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
// integer formatter template instantiations to just one by only using the
@@ -172,6 +159,14 @@ FMT_END_NAMESPACE
# define FMT_REDUCE_INT_INSTANTIATIONS 0
#endif
+FMT_BEGIN_NAMESPACE
+
+template
+struct is_contiguous>
+ : std::true_type {};
+
+namespace detail {
+
// __builtin_clz is broken in clang with Microsoft codegen:
// https://github.com/fmtlib/fmt/issues/519.
#if !FMT_MSC_VERSION
@@ -183,49 +178,30 @@ FMT_END_NAMESPACE
# endif
#endif
-// __builtin_ctz is broken in Intel Compiler Classic on Windows:
-// https://github.com/fmtlib/fmt/issues/2510.
-#ifndef __ICL
-# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
- defined(__NVCOMPILER)
-# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
-# endif
-# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
- FMT_ICC_VERSION || defined(__NVCOMPILER)
-# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
-# endif
-#endif
-
-// Some compilers masquerade as both MSVC and GCC-likes or otherwise support
+// Some compilers masquerade as both MSVC and GCC but otherwise support
// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
// MSVC intrinsics if the clz and clzll builtins are not available.
-#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
- !defined(FMT_BUILTIN_CTZLL)
-FMT_BEGIN_NAMESPACE
-namespace detail {
+#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL)
// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
-# if !defined(__clang__)
-# pragma intrinsic(_BitScanForward)
+# ifndef __clang__
# pragma intrinsic(_BitScanReverse)
-# if defined(_WIN64)
-# pragma intrinsic(_BitScanForward64)
+# ifdef _WIN64
# pragma intrinsic(_BitScanReverse64)
# endif
# endif
inline auto clz(uint32_t x) -> int {
+ FMT_ASSERT(x != 0, "");
+ FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
unsigned long r = 0;
_BitScanReverse(&r, x);
- FMT_ASSERT(x != 0, "");
- // Static analysis complains about using uninitialized data
- // "r", but the only way that can happen is if "x" is 0,
- // which the callers guarantee to not happen.
- FMT_MSC_WARNING(suppress : 6102)
return 31 ^ static_cast(r);
}
# define FMT_BUILTIN_CLZ(n) detail::clz(n)
inline auto clzll(uint64_t x) -> int {
+ FMT_ASSERT(x != 0, "");
+ FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
unsigned long r = 0;
# ifdef _WIN64
_BitScanReverse64(&r, x);
@@ -236,48 +212,10 @@ inline auto clzll(uint64_t x) -> int {
// Scan the low 32 bits.
_BitScanReverse(&r, static_cast(x));
# endif
- FMT_ASSERT(x != 0, "");
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
return 63 ^ static_cast(r);
}
# define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
-
-inline auto ctz(uint32_t x) -> int {
- unsigned long r = 0;
- _BitScanForward(&r, x);
- FMT_ASSERT(x != 0, "");
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
- return static_cast(r);
-}
-# define FMT_BUILTIN_CTZ(n) detail::ctz(n)
-
-inline auto ctzll(uint64_t x) -> int {
- unsigned long r = 0;
- FMT_ASSERT(x != 0, "");
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
-# ifdef _WIN64
- _BitScanForward64(&r, x);
-# else
- // Scan the low 32 bits.
- if (_BitScanForward(&r, static_cast(x))) return static_cast(r);
- // Scan the high 32 bits.
- _BitScanForward(&r, static_cast(x >> 32));
- r += 32;
-# endif
- return static_cast(r);
-}
-# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
-} // namespace detail
-FMT_END_NAMESPACE
-#endif
-
-FMT_BEGIN_NAMESPACE
-
-template
-struct is_contiguous>
- : std::true_type {};
-
-namespace detail {
+#endif // FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL)
FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) {
ignore_unused(condition);
@@ -372,13 +310,14 @@ class uint128_fallback {
-> uint128_fallback {
return {~n.hi_, ~n.lo_};
}
- friend auto operator+(const uint128_fallback& lhs,
- const uint128_fallback& rhs) -> uint128_fallback {
+ friend FMT_CONSTEXPR auto operator+(const uint128_fallback& lhs,
+ const uint128_fallback& rhs)
+ -> uint128_fallback {
auto result = uint128_fallback(lhs);
result += rhs;
return result;
}
- friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
+ friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs)
-> uint128_fallback {
FMT_ASSERT(lhs.hi_ == 0, "");
uint64_t hi = (lhs.lo_ >> 32) * rhs;
@@ -386,7 +325,7 @@ class uint128_fallback {
uint64_t new_lo = (hi << 32) + lo;
return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
}
- friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
+ friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs)
-> uint128_fallback {
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
}
@@ -466,17 +405,17 @@ template <> constexpr auto num_bits() -> int { return 128; }
// and 128-bit pointers to uint128_fallback.
template sizeof(From))>
inline auto bit_cast(const From& from) -> To {
- constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned));
+ constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned short));
struct data_t {
- unsigned value[static_cast(size)];
+ unsigned short value[static_cast(size)];
} data = bit_cast(from);
auto result = To();
if (const_check(is_big_endian())) {
for (int i = 0; i < size; ++i)
- result = (result << num_bits()) | data.value[i];
+ result = (result << num_bits()) | data.value[i];
} else {
for (int i = size - 1; i >= 0; --i)
- result = (result << num_bits()) | data.value[i];
+ result = (result << num_bits()) | data.value[i];
}
return result;
}
@@ -552,8 +491,8 @@ constexpr auto to_pointer(OutputIt, size_t) -> T* {
template
FMT_CONSTEXPR20 auto to_pointer(basic_appender it, size_t n) -> T* {
buffer& buf = get_container(it);
+ buf.try_reserve(buf.size() + n);
auto size = buf.size();
- buf.try_reserve(size + n);
if (buf.capacity() < size + n) return nullptr;
buf.try_resize(size + n);
return buf.data() + size;
@@ -674,7 +613,8 @@ FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) {
auto num_chars_left = to_unsigned(s.data() + s.size() - p);
if (num_chars_left == 0) return;
- FMT_ASSERT(num_chars_left < block_size, "");
+ // Suppress bogus -Wstringop-overflow.
+ if (FMT_GCC_VERSION) num_chars_left &= 3;
char buf[2 * block_size - 1] = {};
copy(p, p + num_chars_left, buf);
const char* buf_ptr = buf;
@@ -728,8 +668,7 @@ FMT_CONSTEXPR inline auto compute_width(string_view s) -> size_t {
template
inline auto code_point_index(basic_string_view s, size_t n) -> size_t {
- size_t size = s.size();
- return n < size ? n : size;
+ return min_of(n, s.size());
}
// Calculates the index of the nth code point in a UTF-8 string.
@@ -796,11 +735,6 @@ using is_double_double = bool_constant::digits == 106>;
# define FMT_USE_FULL_CACHE_DRAGONBOX 0
#endif
-template
-struct is_locale : std::false_type {};
-template
-struct is_locale> : std::true_type {};
-
// An allocator that uses malloc/free to allow removing dependency on the C++
// standard libary runtime.
template struct allocator {
@@ -862,7 +796,7 @@ class basic_memory_buffer : public detail::buffer {
if (size > new_capacity)
new_capacity = size;
else if (new_capacity > max_size)
- new_capacity = size > max_size ? size : max_size;
+ new_capacity = max_of(size, max_size);
T* old_data = buf.data();
T* new_data = self.alloc_.allocate(new_capacity);
// Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
@@ -880,7 +814,7 @@ class basic_memory_buffer : public detail::buffer {
using value_type = T;
using const_reference = const T&;
- FMT_CONSTEXPR20 explicit basic_memory_buffer(
+ FMT_CONSTEXPR explicit basic_memory_buffer(
const Allocator& alloc = Allocator())
: detail::buffer(grow), alloc_(alloc) {
this->set(store_, SIZE);
@@ -928,7 +862,7 @@ class basic_memory_buffer : public detail::buffer {
/// Resizes the buffer to contain `count` elements. If T is a POD type new
/// elements may not be initialized.
- FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); }
+ FMT_CONSTEXPR void resize(size_t count) { this->try_resize(count); }
/// Increases the buffer capacity to `new_capacity`.
void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
@@ -943,7 +877,7 @@ class basic_memory_buffer : public detail::buffer {
using memory_buffer = basic_memory_buffer;
template
-FMT_NODISCARD auto to_string(basic_memory_buffer& buf)
+FMT_NODISCARD auto to_string(const basic_memory_buffer& buf)
-> std::string {
auto size = buf.size();
detail::assume(size < std::string().max_size());
@@ -960,8 +894,8 @@ class writer {
FILE* file_;
public:
- writer(FILE* f) : buf_(nullptr), file_(f) {}
- writer(detail::buffer& buf) : buf_(&buf) {}
+ inline writer(FILE* f) : buf_(nullptr), file_(f) {}
+ inline writer(detail::buffer& buf) : buf_(&buf) {}
/// Formats `args` according to specifications in `fmt` and writes the
/// output to the file.
@@ -979,24 +913,16 @@ class string_buffer {
detail::container_buffer buf_;
public:
- string_buffer() : buf_(str_) {}
+ inline string_buffer() : buf_(str_) {}
- operator writer() { return buf_; }
- std::string& str() { return str_; }
+ inline operator writer() { return buf_; }
+ inline std::string& str() { return str_; }
};
template
struct is_contiguous> : std::true_type {
};
-FMT_END_EXPORT
-namespace detail {
-FMT_API auto write_console(int fd, string_view text) -> bool;
-FMT_API void print(FILE*, string_view);
-} // namespace detail
-
-FMT_BEGIN_EXPORT
-
// Suppress a misleading warning in older versions of clang.
FMT_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables")
@@ -1006,124 +932,36 @@ class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error {
using std::runtime_error::runtime_error;
};
-namespace detail_exported {
-#if FMT_USE_NONTYPE_TEMPLATE_ARGS
+class loc_value;
+
+FMT_END_EXPORT
+namespace detail {
+FMT_API auto write_console(int fd, string_view text) -> bool;
+FMT_API void print(FILE*, string_view);
+} // namespace detail
+
+namespace detail {
template struct fixed_string {
- constexpr fixed_string(const Char (&str)[N]) {
- detail::copy(static_cast(str),
- str + N, data);
+ FMT_CONSTEXPR20 fixed_string(const Char (&s)[N]) {
+ detail::copy(static_cast(s), s + N,
+ data);
}
Char data[N] = {};
};
-#endif // FMT_USE_NONTYPE_TEMPLATE_ARGS
// Converts a compile-time string to basic_string_view.
-template
+FMT_EXPORT template
constexpr auto compile_string_to_view(const Char (&s)[N])
-> basic_string_view {
// Remove trailing NUL character if needed. Won't be present if this is used
// with a raw character array (i.e. not defined as a string).
return {s, N - (std::char_traits::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
}
-template
+FMT_EXPORT template
constexpr auto compile_string_to_view(basic_string_view s)
-> basic_string_view {
return s;
}
-} // namespace detail_exported
-
-// A generic formatting context with custom output iterator and character
-// (code unit) support. Char is the format string code unit type which can be
-// different from OutputIt::value_type.
-template class generic_context {
- private:
- OutputIt out_;
- basic_format_args args_;
- detail::locale_ref loc_;
-
- public:
- using char_type = Char;
- using iterator = OutputIt;
- using parse_context_type FMT_DEPRECATED = parse_context;
- template
- using formatter_type FMT_DEPRECATED = formatter;
- enum { builtin_types = FMT_BUILTIN_TYPES };
-
- constexpr generic_context(OutputIt out,
- basic_format_args args,
- detail::locale_ref loc = {})
- : out_(out), args_(args), loc_(loc) {}
- generic_context(generic_context&&) = default;
- generic_context(const generic_context&) = delete;
- void operator=(const generic_context&) = delete;
-
- constexpr auto arg(int id) const -> basic_format_arg {
- return args_.get(id);
- }
- auto arg(basic_string_view name) -> basic_format_arg {
- return args_.get(name);
- }
- FMT_CONSTEXPR auto arg_id(basic_string_view name) -> int {
- return args_.get_id(name);
- }
-
- FMT_CONSTEXPR auto out() -> iterator { return out_; }
-
- void advance_to(iterator it) {
- if (!detail::is_back_insert_iterator()) out_ = it;
- }
-
- FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; }
-};
-
-class loc_value {
- private:
- basic_format_arg value_;
-
- public:
- template ::value)>
- loc_value(T value) : value_(value) {}
-
- template ::value)>
- loc_value(T) {}
-
- template auto visit(Visitor&& vis) -> decltype(vis(0)) {
- return value_.visit(vis);
- }
-};
-
-// A locale facet that formats values in UTF-8.
-// It is parameterized on the locale to avoid the heavy include.
-template class format_facet : public Locale::facet {
- private:
- std::string separator_;
- std::string grouping_;
- std::string decimal_point_;
-
- protected:
- virtual auto do_put(appender out, loc_value val,
- const format_specs& specs) const -> bool;
-
- public:
- static FMT_API typename Locale::id id;
-
- explicit format_facet(Locale& loc);
- explicit format_facet(string_view sep = "",
- std::initializer_list g = {3},
- std::string decimal_point = ".")
- : separator_(sep.data(), sep.size()),
- grouping_(g.begin(), g.end()),
- decimal_point_(decimal_point) {}
-
- auto put(appender out, loc_value val, const format_specs& specs) const
- -> bool {
- return do_put(out, val, specs);
- }
-};
-
-FMT_END_EXPORT
-
-namespace detail {
// Returns true if value is negative, false otherwise.
// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
@@ -1302,6 +1140,17 @@ template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
return decimal_point_impl(loc);
}
+#ifndef FMT_HEADER_ONLY
+FMT_BEGIN_EXPORT
+extern template FMT_API auto thousands_sep_impl