From 1d1d746d996b5210bbebb0c0625470d9071fada8 Mon Sep 17 00:00:00 2001
From: Simon Judd
Date: Fri, 27 Dec 2024 17:07:17 +1030
Subject: [PATCH 1/8] Allow mouse movement while left click is pressed on a
toolbar button
Should make the buttons less finnicky
---
src/UI/SToolBar/SToolBarButton.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/UI/SToolBar/SToolBarButton.cpp b/src/UI/SToolBar/SToolBarButton.cpp
index 03d60e975..89bd68864 100644
--- a/src/UI/SToolBar/SToolBarButton.cpp
+++ b/src/UI/SToolBar/SToolBarButton.cpp
@@ -221,7 +221,7 @@ bool SToolBarButton::updateState(int mouse_event)
auto prev_state = state_;
if (mouse_event == 1) // Enter or motion
- state_ = State::MouseOver;
+ state_ = wxGetMouseState().LeftIsDown() ? State::MouseDown : State::MouseOver;
else if (mouse_event == 2) // Leave
state_ = State::Normal;
else if (IsShownOnScreen() && IsEnabled())
From bf00e9f8ffc35d48c1b3d8dd85d7a37731ebd235 Mon Sep 17 00:00:00 2001
From: Simon Judd
Date: Tue, 31 Dec 2024 17:18:06 +1030
Subject: [PATCH 2/8] Various MIDI/Fluidsynth fixes and improvements
- Use pulseaudio instead of alsa as the default driver on linux (Fix #1147)
- Add 'default-GM.sf2' to linux soundfont path detection, looks like this changed since the detection was originally added
- Stop all notes when pausing/stopping fluidsynth, hopefully this fixes some notes getting stuck playing when switching between MIDI entries
---
src/Audio/MIDIPlayer.cpp | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/Audio/MIDIPlayer.cpp b/src/Audio/MIDIPlayer.cpp
index 1521a6af9..bd4762fe9 100644
--- a/src/Audio/MIDIPlayer.cpp
+++ b/src/Audio/MIDIPlayer.cpp
@@ -90,15 +90,18 @@ class FluidSynthMIDIPlayer : public MIDIPlayer
fs_initialised_ = false;
file_ = "";
- // Set fluidsynth driver to alsa in linux (no idea why it defaults to jack)
+ // Set fluidsynth driver to pulseaudio in linux (no idea why it defaults to jack)
if (app::platform() == app::Platform::Linux && fs_driver.value.empty())
- fs_driver = "alsa";
+ fs_driver = "pulseaudio";
// Init soundfont path
if (fs_soundfont_path.value.empty())
{
if (app::platform() == app::Platform::Linux)
- fs_soundfont_path = "/usr/share/sounds/sf2/FluidR3_GM.sf2:/usr/share/sounds/sf2/FluidR3_GS.sf2";
+ fs_soundfont_path =
+ "/usr/share/sounds/sf2/FluidR3_GM.sf2"
+ ":/usr/share/sounds/sf2/FluidR3_GS.sf2"
+ ":/usr/share/sounds/sf2/default-GM.sf2";
else
log::warning(1, "No FluidSynth soundfont set, MIDI playback will not work");
}
@@ -249,7 +252,10 @@ class FluidSynthMIDIPlayer : public MIDIPlayer
elapsed_ms_ += timer_.getElapsedTime().asMilliseconds();
- return fluid_player_stop(fs_player_) == FLUID_OK;
+ auto ok = fluid_player_stop(fs_player_) == FLUID_OK;
+ fluid_synth_all_notes_off(fs_synth_, -1);
+
+ return ok;
}
// -------------------------------------------------------------------------
@@ -257,9 +263,8 @@ class FluidSynthMIDIPlayer : public MIDIPlayer
// -------------------------------------------------------------------------
bool stop() override
{
- if (isPlaying())
- fluid_player_stop(fs_player_);
-
+ fluid_player_stop(fs_player_);
+ fluid_synth_all_notes_off(fs_synth_, -1);
fluid_player_seek(fs_player_, 0);
elapsed_ms_ = 0;
From 3baac1241dc34bb730d2763c720b4a03c708e0a8 Mon Sep 17 00:00:00 2001
From: Pedro Beirao <82064173+Pedro-Beirao@users.noreply.github.com>
Date: Wed, 8 Jan 2025 10:25:28 +0000
Subject: [PATCH 3/8] Add macOS CI artifacts uploading (#1770)
---
.github/workflows/continuous_integration.yml | 88 +++++++++++++-------
1 file changed, 59 insertions(+), 29 deletions(-)
diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml
index a93fbf70b..3eb728da9 100644
--- a/.github/workflows/continuous_integration.yml
+++ b/.github/workflows/continuous_integration.yml
@@ -6,51 +6,81 @@ jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
+ defaults:
+ run:
+ shell: ${{ matrix.config.shell }}
strategy:
fail-fast: false
matrix:
config:
- - {
- name: "macOS",
- os: macos-latest,
- deps_cmdline: "brew install fluidsynth freeimage ftgl lua mpg123 sfml wxwidgets"
- }
- - {
- name: "Linux GCC",
- os: ubuntu-24.04,
- deps_cmdline: "sudo apt install \
- libfluidsynth-dev libfreeimage-dev libwebkit2gtk-4.1-dev \
- libftgl-dev liblua5.3-dev libmpg123-dev libsfml-dev \
- libwxgtk3.2-dev libwxgtk-webview3.2-dev"
- }
- - {
- name: "Linux Clang",
- os: ubuntu-24.04,
- extra_options: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++",
- deps_cmdline: "sudo apt install \
- libfluidsynth-dev libfreeimage-dev libwebkit2gtk-4.1-dev \
- libftgl-dev liblua5.3-dev libmpg123-dev libsfml-dev \
- libwxgtk3.2-dev libwxgtk-webview3.2-dev"
- }
+ - name: "macOS arm64"
+ os: macos-latest
+ release: true
+ shell: bash
+ package_name: "mac_arm64"
+ artifact-path: build/*.dmg
+
+ - name: "macOS x64"
+ os: macos-13
+ release: true
+ shell: bash
+ package_name: "mac_x64"
+ artifact-path: build/*.dmg
+
+ - name: "Linux GCC"
+ os: ubuntu-24.04
+ shell: bash
+
+ - name: "Linux Clang"
+ os: ubuntu-24.04
+ shell: bash
+ extra_options: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
steps:
- uses: actions/checkout@v2
- - name: Install Dependencies
- shell: bash
+ - name: Install Dependencies (macOS)
+ if: runner.os == 'macOS'
+ run: brew install fluidsynth freeimage ftgl lua mpg123 sfml wxwidgets dylibbundler create-dmg
+
+ - name: Install Dependencies (Linux)
+ if: runner.os == 'Linux'
run: |
- if [[ ! -z "${{ matrix.config.deps_cmdline }}" ]]; then
- eval ${{ matrix.config.deps_cmdline }}
- fi
+ sudo apt-get update
+ sudo apt-get upgrade
+ sudo apt-get install \
+ libfluidsynth-dev libfreeimage-dev libwebkit2gtk-4.1-dev \
+ libftgl-dev liblua5.3-dev libmpg123-dev libsfml-dev \
+ libwxgtk3.2-dev libwxgtk-webview3.2-dev
- name: Configure
- shell: bash
run: |
mkdir build
cmake -B build ${{ matrix.config.extra_options }} .
- name: Build
- shell: bash
run: |
export MAKEFLAGS=--keep-going
cmake --build build --parallel 3
+
+ - name: Package (macOS)
+ if: runner.os == 'macOS'
+ run: |
+ cd build
+ dylibbundler -od -b -x slade.app/Contents/MacOS/slade -d slade.app/Contents/MacOS/libs -p @executable_path/libs
+ create-dmg --app-drop-link 10 10 ./slade_${{ matrix.config.package_name }}_${{ github.ref_name }}.dmg ./slade.app
+
+ - name: Upload Artifacts
+ if: ${{ matrix.config.package_name }}
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ matrix.config.package_name }}
+ path: ${{ matrix.config.artifact-path }}
+
+ - name: Release
+ if: ${{ contains(github.ref, 'tags') && matrix.config.release }}
+ uses: ncipollo/release-action@v1
+ with:
+ name: ${{ github.ref_name }}
+ allowUpdates: true
+ artifacts: ${{ matrix.config.artifact-path }}
From e1e9c5d4e024618c31317b3772f34d4118478235 Mon Sep 17 00:00:00 2001
From: Simon Judd
Date: Mon, 20 Jan 2025 15:50:44 +1030
Subject: [PATCH 4/8] Update .readthedocs.yml
Apparently the 'build' section is required now, builds have been failing for a while because it was missing
---
.readthedocs.yml | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 7dee082ee..3e82b09b3 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -9,6 +9,12 @@ version: 2
#sphinx:
# configuration: docs/conf.py
+# Set the version of Python and other tools you might need
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.12"
+
# Build documentation with MkDocs
mkdocs:
configuration: docs/mkdocs.yml
@@ -19,6 +25,6 @@ mkdocs:
# Optionally set the version of Python and requirements required to build your docs
python:
- version: 3.7
+ version: 3.12
install:
- requirements: docs/requirements.txt
From f2eff2fc59c20fcf69649303b1c0475975b25115 Mon Sep 17 00:00:00 2001
From: Simon Judd
Date: Mon, 20 Jan 2025 15:53:00 +1030
Subject: [PATCH 5/8] Update .readthedocs.yml
Also need to remove the version from the python section apparently, I guess because it moved to the build section
---
.readthedocs.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 3e82b09b3..06a53a290 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -25,6 +25,5 @@ mkdocs:
# Optionally set the version of Python and requirements required to build your docs
python:
- version: 3.12
install:
- requirements: docs/requirements.txt
From d6ffbe320b603ef33c2821e78cb208838aed10c1 Mon Sep 17 00:00:00 2001
From: Pedro Beirao <82064173+Pedro-Beirao@users.noreply.github.com>
Date: Mon, 20 Jan 2025 10:05:46 +0000
Subject: [PATCH 6/8] Small CI fixes (#1773)
* Dont delete release description when uploading artifacts
* Add retry create dmg step on macOS CI
---
.github/workflows/continuous_integration.yml | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml
index 3eb728da9..2f88e4288 100644
--- a/.github/workflows/continuous_integration.yml
+++ b/.github/workflows/continuous_integration.yml
@@ -68,7 +68,17 @@ jobs:
run: |
cd build
dylibbundler -od -b -x slade.app/Contents/MacOS/slade -d slade.app/Contents/MacOS/libs -p @executable_path/libs
- create-dmg --app-drop-link 10 10 ./slade_${{ matrix.config.package_name }}_${{ github.ref_name }}.dmg ./slade.app
+
+ for i in {1..10};
+ do
+ if create-dmg --app-drop-link 10 10 ./slade_${{ matrix.config.package_name }}_${{ github.ref_name }}.dmg ./slade.app;
+ then
+ echo "slade_${{ matrix.config.package_name }}_${{ github.ref_name }}.dmg created"
+ break
+ else
+ echo "create-dmg failed $i"
+ fi
+ done
- name: Upload Artifacts
if: ${{ matrix.config.package_name }}
@@ -83,4 +93,5 @@ jobs:
with:
name: ${{ github.ref_name }}
allowUpdates: true
+ omitBodyDuringUpdate: true
artifacts: ${{ matrix.config.artifact-path }}
From c71f5841bdd7c9383d189e8a8001191aecdb792d Mon Sep 17 00:00:00 2001
From: Simon Judd
Date: Thu, 30 Jan 2025 14:22:51 +1030
Subject: [PATCH 7/8] Fix //$ editor comment parsing for DECORATE and ZScript
Hopefully the ZScript part is ok
Fix #1774
---
src/Game/Decorate.cpp | 4 ++--
src/Game/ZScript.cpp | 10 +++++++++-
src/Utility/Tokenizer.cpp | 28 ++++++++++++++++++++--------
src/Utility/Tokenizer.h | 26 ++++++++++++++------------
4 files changed, 45 insertions(+), 23 deletions(-)
diff --git a/src/Game/Decorate.cpp b/src/Game/Decorate.cpp
index 4a4d49bfc..3c12d665d 100644
--- a/src/Game/Decorate.cpp
+++ b/src/Game/Decorate.cpp
@@ -283,8 +283,7 @@ void parseDecorateActor(Tokenizer& tz, std::map& types, vector& types, ve
// Init tokenizer
Tokenizer tz;
tz.setSpecialCharacters(":,{}");
+ tz.enableEditorComments();
tz.openMem(entry->data(), entry->name());
// --- Parse ---
diff --git a/src/Game/ZScript.cpp b/src/Game/ZScript.cpp
index 80232d7ea..5ed5b5976 100644
--- a/src/Game/ZScript.cpp
+++ b/src/Game/ZScript.cpp
@@ -208,6 +208,7 @@ void parseBlocks(ArchiveEntry* entry, vector& parsed, vector");
tz.setCommentTypes(Tokenizer::CommentTypes::CPPStyle | Tokenizer::CommentTypes::CStyle);
+ tz.enableEditorComments();
tz.openMem(entry->data(), "ZScript");
entry_stack.push_back(entry);
@@ -869,9 +870,16 @@ bool Class::parseClassBlock(vector& block)
else if (strutil::equalCI(first_token, "states"))
states_.parse(statement);
- // DB property comment
+ // DB property comment(s)
else if (strutil::startsWith(first_token, editor_comment_prefix))
+ {
db_properties_.emplace_back(Tokenizer::parseEditorComment(first_token));
+ for (auto i = 1; i < statement.tokens.size(); ++i)
+ {
+ if (strutil::startsWith(statement.tokens[i], editor_comment_prefix))
+ db_properties_.emplace_back(Tokenizer::parseEditorComment(statement.tokens[i]));
+ }
+ }
// Function
else if (Function::isFunction(statement))
diff --git a/src/Utility/Tokenizer.cpp b/src/Utility/Tokenizer.cpp
index fc48cbff6..9cd19023e 100644
--- a/src/Utility/Tokenizer.cpp
+++ b/src/Utility/Tokenizer.cpp
@@ -82,7 +82,7 @@ bool isWhitespace(char p)
std::pair Tokenizer::parseEditorComment(string_view token)
{
// Find the first space
- size_t spos = token.find(" \t");
+ size_t spos = token.find_first_of(" \t");
if (spos == string_view::npos)
{
string key(token.substr(3));
@@ -721,7 +721,7 @@ void Tokenizer::reset()
// Checks if a comment begins at the current position and returns the comment
// type if one does (0 otherwise)
// -----------------------------------------------------------------------------
-unsigned Tokenizer::checkCommentBegin()
+unsigned Tokenizer::checkCommentBegin() const
{
// C-Style comment (/*)
if (comment_types_ & CStyle && state_.position + 1 < state_.size && data_[state_.position] == '/'
@@ -838,13 +838,12 @@ void Tokenizer::tokenizeToken()
}
// Check for end of token
- if (isWhitespace(data_[state_.position]) || // Whitespace
- isSpecialCharacter(data_[state_.position]) || // Special character
- checkCommentBegin() > 0) // Comment
+ if (isEndOfToken())
{
// End token
- state_.state = TokenizeState::State::Unknown;
- state_.done = true;
+ state_.state = TokenizeState::State::Unknown;
+ state_.done = true;
+ state_.to_eol = false;
return;
}
@@ -859,7 +858,7 @@ void Tokenizer::tokenizeToken()
void Tokenizer::tokenizeComment()
{
// Check for decorate //$
- if (decorate_ && state_.comment_type == CPPStyle)
+ if (editor_comments_ && state_.comment_type == CPPStyle)
{
if (data_[state_.position] == '$' && data_[state_.position - 1] == '/' && data_[state_.position - 2] == '/')
{
@@ -868,6 +867,7 @@ void Tokenizer::tokenizeComment()
state_.current_token.quoted_string = false;
state_.current_token.pos_start = state_.position - 2;
state_.state = TokenizeState::State::Token;
+ state_.to_eol = true;
return;
}
}
@@ -991,6 +991,18 @@ void Tokenizer::resetToLineStart()
}
}
+bool Tokenizer::isEndOfToken() const
+{
+ // Token is to end of line, only ends on newline
+ if (state_.to_eol)
+ return data_[state_.position] == '\n';
+
+ // Regular token
+ return isWhitespace(data_[state_.position]) || // Whitespace
+ isSpecialCharacter(data_[state_.position]) || // Special character
+ checkCommentBegin() > 0; // Comment
+}
+
// Testing
diff --git a/src/Utility/Tokenizer.h b/src/Utility/Tokenizer.h
index 4ac37e09e..6fb557909 100644
--- a/src/Utility/Tokenizer.h
+++ b/src/Utility/Tokenizer.h
@@ -67,7 +67,8 @@ class Tokenizer
unsigned current_line = 1;
unsigned comment_type = 0;
Token current_token;
- bool done = false;
+ bool done = false;
+ bool to_eol = false;
};
static std::pair parseEditorComment(string_view token);
@@ -77,7 +78,7 @@ class Tokenizer
// Accessors
const string& source() const { return source_; }
- bool decorate() const { return decorate_; }
+ bool decorate() const { return editor_comments_; }
bool readLowerCase() const { return read_lowercase_; }
const Token& current() const { return token_current_; }
const Token& peek() const;
@@ -90,8 +91,8 @@ class Tokenizer
}
void setSource(const wxString& source) { source_ = source; }
void setReadLowerCase(bool lower) { read_lowercase_ = lower; }
- void enableDecorate(bool enable) { decorate_ = enable; }
- void enableDebug(bool enable) { debug_ = enable; }
+ void enableEditorComments(bool enable = true) { editor_comments_ = enable; }
+ void enableDebug(bool enable = true) { debug_ = enable; }
// Token Iterating
const Token& next();
@@ -212,19 +213,19 @@ class Tokenizer
TokenizeState state_ = {};
// Configuration
- int comment_types_; // Types of comments to skip
- vector special_characters_; // These will always be read as separate tokens
- string source_; // What file/entry/chunk is being tokenized
- bool decorate_ = false; // Special handling for //$ comments
- bool read_lowercase_ = false; // If true, tokens will all be read in lowercase
- // (except for quoted strings, obviously)
- bool debug_ = false; // Log each token read
+ int comment_types_; // Types of comments to skip
+ vector special_characters_; // These will always be read as separate tokens
+ string source_; // What file/entry/chunk is being tokenized
+ bool editor_comments_ = false; // Special handling for //$ comments
+ bool read_lowercase_ = false; // If true, tokens will all be read in lowercase
+ // (except for quoted strings, obviously)
+ bool debug_ = false; // Log each token read
// Static
static Token invalid_token_;
// Tokenizing
- unsigned checkCommentBegin();
+ unsigned checkCommentBegin() const;
void tokenizeUnknown();
void tokenizeToken();
void tokenizeComment();
@@ -232,5 +233,6 @@ class Tokenizer
bool readNext(Token* target);
bool readNext() { return readNext(&token_next_); }
void resetToLineStart();
+ bool isEndOfToken() const;
};
} // namespace slade
From 041673e1fa49933670eb523b9e4261c9b3a40515 Mon Sep 17 00:00:00 2001
From: unawarez <114197348+unawarez@users.noreply.github.com>
Date: Fri, 31 Jan 2025 00:58:00 -0600
Subject: [PATCH 8/8] Update bundled fmt to 11.1.3 to fix macOS compile errors
(#1776)
Before the build would fail with a bunch of errors like this:
/Users/me/doom/slade/thirdparty/fmt/src/os.cc:379:6: error: use of undeclared identifier 'file_buffer'
---
thirdparty/fmt/.clang-format | 6 +
thirdparty/fmt/CMakeLists.txt | 38 +-
thirdparty/fmt/ChangeLog.md | 296 ++
thirdparty/fmt/README.md | 1 +
thirdparty/fmt/doc/api.md | 69 +-
thirdparty/fmt/doc/get-started.md | 2 +-
thirdparty/fmt/doc/index.md | 4 +-
thirdparty/fmt/doc/syntax.md | 9 +-
thirdparty/fmt/include/fmt/args.h | 48 +-
thirdparty/fmt/include/fmt/base.h | 3652 ++++++++---------
thirdparty/fmt/include/fmt/chrono.h | 846 ++--
thirdparty/fmt/include/fmt/color.h | 42 +-
thirdparty/fmt/include/fmt/compile.h | 70 +-
thirdparty/fmt/include/fmt/format-inl.h | 109 +-
thirdparty/fmt/include/fmt/format.h | 2375 +++++------
thirdparty/fmt/include/fmt/os.h | 98 +-
thirdparty/fmt/include/fmt/ostream.h | 131 +-
thirdparty/fmt/include/fmt/printf.h | 237 +-
thirdparty/fmt/include/fmt/ranges.h | 228 +-
thirdparty/fmt/include/fmt/std.h | 121 +-
thirdparty/fmt/include/fmt/xchar.h | 143 +-
thirdparty/fmt/src/fmt.cc | 20 +-
thirdparty/fmt/src/format.cc | 5 +-
thirdparty/fmt/src/os.cc | 17 +-
thirdparty/fmt/support/check-commits | 0
thirdparty/fmt/support/mkdocs | 38 +-
.../mkdocstrings_handlers/cxx/__init__.py | 601 +--
.../fmt/support/{manage.py => release.py} | 92 +-
28 files changed, 4634 insertions(+), 4664 deletions(-)
mode change 100644 => 100755 thirdparty/fmt/support/check-commits
mode change 100644 => 100755 thirdparty/fmt/support/mkdocs
rename thirdparty/fmt/support/{manage.py => release.py} (69%)
diff --git a/thirdparty/fmt/.clang-format b/thirdparty/fmt/.clang-format
index df55d340f..31f8c343e 100644
--- a/thirdparty/fmt/.clang-format
+++ b/thirdparty/fmt/.clang-format
@@ -6,3 +6,9 @@ IndentPPDirectives: AfterHash
IndentCaseLabels: false
AlwaysBreakTemplateDeclarations: false
DerivePointerAlignment: false
+AllowShortCaseLabelsOnASingleLine: true
+AlignConsecutiveShortCaseStatements:
+ Enabled: true
+ AcrossEmptyLines: true
+ AcrossComments: true
+ AlignCaseColons: false
\ No newline at end of file
diff --git a/thirdparty/fmt/CMakeLists.txt b/thirdparty/fmt/CMakeLists.txt
index e3b35110f..8df6670d2 100644
--- a/thirdparty/fmt/CMakeLists.txt
+++ b/thirdparty/fmt/CMakeLists.txt
@@ -69,8 +69,6 @@ function(add_module_library name)
target_compile_options(${name} PUBLIC -fmodules-ts)
endif ()
- target_compile_definitions(${name} PRIVATE FMT_MODULE)
-
if (FMT_USE_CMAKE_MODULES)
target_sources(${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES
FILES ${sources})
@@ -240,7 +238,13 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
endif ()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2
- -Wnull-dereference -Wduplicated-cond)
+ -Wduplicated-cond)
+ # Workaround for GCC regression
+ # [12/13/14/15 regression] New (since gcc 12) false positive null-dereference in vector.resize
+ # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108860
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
+ set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnull-dereference)
+ endif ()
endif ()
set(WERROR_FLAG -Werror)
endif ()
@@ -289,6 +293,7 @@ function(add_headers VAR)
endfunction()
# Define the fmt library, its includes and the needed defines.
+set(FMT_HEADERS)
add_headers(FMT_HEADERS args.h base.h chrono.h color.h compile.h core.h format.h
format-inl.h os.h ostream.h printf.h ranges.h std.h
xchar.h)
@@ -319,7 +324,7 @@ else ()
message(WARNING "Feature cxx_std_11 is unknown for the CXX compiler")
endif ()
-target_include_directories(fmt ${FMT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
+target_include_directories(fmt ${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE PUBLIC
$
$)
@@ -359,8 +364,8 @@ 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 $<$:/utf-8>)
- target_compile_options(fmt-header-only INTERFACE $<$:/utf-8>)
+ target_compile_options(fmt PUBLIC $<$,$>:/utf-8>)
+ target_compile_options(fmt-header-only INTERFACE $<$,$>:/utf-8>)
else ()
target_compile_definitions(fmt PUBLIC FMT_UNICODE=0)
endif ()
@@ -369,7 +374,7 @@ target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
target_compile_features(fmt-header-only INTERFACE cxx_std_11)
target_include_directories(fmt-header-only
- ${FMT_SYSTEM_HEADERS_ATTRIBUTE} INTERFACE
+ ${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE INTERFACE
$
$)
@@ -420,7 +425,9 @@ if (FMT_INSTALL)
endif()
# Install the library and headers.
- install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
+ install(TARGETS ${INSTALL_TARGETS}
+ COMPONENT fmt-core
+ EXPORT ${targets_export_name}
LIBRARY DESTINATION ${FMT_LIB_DIR}
ARCHIVE DESTINATION ${FMT_LIB_DIR}
PUBLIC_HEADER DESTINATION "${FMT_INC_DIR}/fmt"
@@ -433,13 +440,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 fmt-core)
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR}
- NAMESPACE fmt::)
+ NAMESPACE fmt::
+ COMPONENT fmt-core)
- install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
+ install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}"
+ COMPONENT fmt-core)
endif ()
function(add_doc_target)
@@ -475,7 +484,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 fmt-doc OPTIONAL)
endfunction()
if (FMT_DOC)
diff --git a/thirdparty/fmt/ChangeLog.md b/thirdparty/fmt/ChangeLog.md
index 6ba567d1d..2784c67b7 100644
--- a/thirdparty/fmt/ChangeLog.md
+++ b/thirdparty/fmt/ChangeLog.md
@@ -1,3 +1,296 @@
+# 11.1.3 - 2025-01-25
+
+- Fixed compilation on GCC 9.4 (https://github.com/fmtlib/fmt/issues/4313).
+
+- Worked around an internal compiler error when using C++20 modules with GCC
+ 14.2 and earlier (https://github.com/fmtlib/fmt/issues/4295).
+
+- Worked around a bug in GCC 6 (https://github.com/fmtlib/fmt/issues/4318).
+
+- Fixed an issue caused by instantiating `formatter`
+ (https://github.com/fmtlib/fmt/issues/4303,
+ https://github.com/fmtlib/fmt/pull/4325). Thanks @timsong-cpp.
+
+- Fixed formatting into `std::ostreambuf_iterator` when using format string
+ compilation (https://github.com/fmtlib/fmt/issues/4309,
+ https://github.com/fmtlib/fmt/pull/4312). Thanks @phprus.
+
+- Restored a constraint on the map formatter so that it correctly reports as
+ unformattable when the element is (https://github.com/fmtlib/fmt/pull/4326).
+ Thanks @timsong-cpp.
+
+- Reduced the size of format specs (https://github.com/fmtlib/fmt/issues/4298).
+
+- Readded `args()` to `fmt::format_context`
+ (https://github.com/fmtlib/fmt/issues/4307,
+ https://github.com/fmtlib/fmt/pull/4310). Thanks @Erroneous1.
+
+- Fixed a bogus MSVC warning (https://github.com/fmtlib/fmt/issues/4314,
+ https://github.com/fmtlib/fmt/pull/4322). Thanks @ZehMatt.
+
+- Fixed a pedantic mode error in the CMake config
+ (https://github.com/fmtlib/fmt/pull/4327). Thanks @rlalik.
+
+# 11.1.2 - 2025-01-12
+
+- Fixed ABI compatibility with earlier 11.x versions
+ (https://github.com/fmtlib/fmt/issues/4292).
+
+- Added `wchar_t` support to the `std::bitset` formatter
+ (https://github.com/fmtlib/fmt/issues/4285,
+ https://github.com/fmtlib/fmt/pull/4286,
+ https://github.com/fmtlib/fmt/issues/4289,
+ https://github.com/fmtlib/fmt/pull/4290). Thanks @phprus.
+
+- Prefixed CMake components with `fmt-` to simplify usage of {fmt} via
+ `add_subdirectory` (https://github.com/fmtlib/fmt/issues/4283).
+
+- Updated docs for meson (https://github.com/fmtlib/fmt/pull/4291).
+ Thanks @trim21.
+
+- Fixed a compilation error in chrono on nvcc
+ (https://github.com/fmtlib/fmt/issues/4297,
+ https://github.com/fmtlib/fmt/pull/4301). Thanks @breyerml.
+
+- Fixed various warnings
+ (https://github.com/fmtlib/fmt/pull/4288,
+ https://github.com/fmtlib/fmt/pull/4299). Thanks @GamesTrap and @edo9300.
+
+# 11.1.1 - 2024-12-27
+
+- 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
- Fixed compatibility with non-POSIX systems
@@ -268,6 +561,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/thirdparty/fmt/README.md b/thirdparty/fmt/README.md
index 5f9249d4b..fd845db20 100644
--- a/thirdparty/fmt/README.md
+++ b/thirdparty/fmt/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/thirdparty/fmt/doc/api.md b/thirdparty/fmt/doc/api.md
index bf0df7315..80296ea4e 100644
--- a/thirdparty/fmt/doc/api.md
+++ b/thirdparty/fmt/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
@@ -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/thirdparty/fmt/doc/get-started.md b/thirdparty/fmt/doc/get-started.md
index e61da8829..466d1c1b2 100644
--- a/thirdparty/fmt/doc/get-started.md
+++ b/thirdparty/fmt/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/thirdparty/fmt/doc/index.md b/thirdparty/fmt/doc/index.md
index 457857c4f..4f28e114f 100644
--- a/thirdparty/fmt/doc/index.md
+++ b/thirdparty/fmt/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.8, 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/thirdparty/fmt/doc/syntax.md b/thirdparty/fmt/doc/syntax.md
index 87fa53f84..46d7d2fd2 100644
--- a/thirdparty/fmt/doc/syntax.md
+++ b/thirdparty/fmt/doc/syntax.md
@@ -589,8 +589,7 @@ The available presentation types (*chrono_type*) are:
represented with seconds, then the format is a decimal floating-point number
with a fixed format and a precision matching that of the precision of the
input (or to a microseconds precision if the conversion to floating-point
- decimal seconds cannot be made within 18 fractional digits). The character
- for the decimal point is localized according to the locale. The modified
+ decimal seconds cannot be made within 18 fractional digits). The modified
command %OS
produces the locale's alternative representation.
@@ -707,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'` and `'W'` presentation types.
+`'V'`, `'W'`, `'Y'`, `'d'`, `'j'` and `'m'` presentation types.
## Range Format Specifications
diff --git a/thirdparty/fmt/include/fmt/args.h b/thirdparty/fmt/include/fmt/args.h
index 31a60e8fa..3ff478807 100644
--- a/thirdparty/fmt/include/fmt/args.h
+++ b/thirdparty/fmt/include/fmt/args.h
@@ -17,7 +17,6 @@
#include "format.h" // std_string_view
FMT_BEGIN_NAMESPACE
-
namespace detail {
template struct is_reference_wrapper : std::false_type {};
@@ -72,19 +71,13 @@ class dynamic_arg_list {
* It can be implicitly converted into `fmt::basic_format_args` for passing
* into type-erased formatting functions such as `fmt::vformat`.
*/
-template
-class dynamic_format_arg_store
-#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
- // Workaround a GCC template argument substitution bug.
- : public basic_format_args
-#endif
-{
+template class dynamic_format_arg_store {
private:
using char_type = typename Context::char_type;
template struct need_copy {
static constexpr detail::type mapped_type =
- detail::mapped_type_constant::value;
+ detail::mapped_type_constant::value;
enum {
value = !(detail::is_reference_wrapper::value ||
@@ -97,7 +90,7 @@ class dynamic_format_arg_store
};
template
- using stored_type = conditional_t<
+ using stored_t = conditional_t<
std::is_convertible>::value &&
!detail::is_reference_wrapper::value,
std::basic_string, T>;
@@ -112,41 +105,37 @@ class dynamic_format_arg_store
friend class basic_format_args;
- auto get_types() const -> unsigned long long {
- return detail::is_unpacked_bit | data_.size() |
- (named_info_.empty()
- ? 0ULL
- : static_cast(detail::has_named_args_bit));
- }
-
auto data() const -> const basic_format_arg* {
return named_info_.empty() ? data_.data() : data_.data() + 1;
}
template void emplace_arg(const T& arg) {
- data_.emplace_back(detail::make_arg(arg));
+ data_.emplace_back(arg);
}
template
void emplace_arg(const detail::named_arg& arg) {
- if (named_info_.empty()) {
- constexpr const detail::named_arg_info* zero_ptr{nullptr};
- data_.insert(data_.begin(), {zero_ptr, 0});
- }
- data_.emplace_back(detail::make_arg(detail::unwrap(arg.value)));
+ if (named_info_.empty())
+ data_.insert(data_.begin(), basic_format_arg(nullptr, 0));
+ data_.emplace_back(detail::unwrap(arg.value));
auto pop_one = [](std::vector>* data) {
data->pop_back();
};
std::unique_ptr>, decltype(pop_one)>
guard{&data_, pop_one};
named_info_.push_back({arg.name, static_cast(data_.size() - 2u)});
- data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
+ data_[0] = {named_info_.data(), named_info_.size()};
guard.release();
}
public:
constexpr dynamic_format_arg_store() = default;
+ operator basic_format_args() const {
+ return basic_format_args(data(), static_cast(data_.size()),
+ !named_info_.empty());
+ }
+
/**
* Adds an argument into the dynamic store for later passing to a formatting
* function.
@@ -164,7 +153,7 @@ class dynamic_format_arg_store
*/
template void push_back(const T& arg) {
if (detail::const_check(need_copy::value))
- emplace_arg(dynamic_args_.push>(arg));
+ emplace_arg(dynamic_args_.push>(arg));
else
emplace_arg(detail::unwrap(arg));
}
@@ -200,7 +189,7 @@ class dynamic_format_arg_store
dynamic_args_.push>(arg.name).c_str();
if (detail::const_check(need_copy::value)) {
emplace_arg(
- fmt::arg(arg_name, dynamic_args_.push>(arg.value)));
+ fmt::arg(arg_name, dynamic_args_.push>(arg.value)));
} else {
emplace_arg(fmt::arg(arg_name, arg.value));
}
@@ -210,17 +199,20 @@ class dynamic_format_arg_store
void clear() {
data_.clear();
named_info_.clear();
- dynamic_args_ = detail::dynamic_arg_list();
+ dynamic_args_ = {};
}
/// Reserves space to store at least `new_cap` arguments including
/// `new_cap_named` named arguments.
void reserve(size_t new_cap, size_t new_cap_named) {
FMT_ASSERT(new_cap >= new_cap_named,
- "Set of arguments includes set of named arguments");
+ "set of arguments includes set of named arguments");
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/thirdparty/fmt/include/fmt/base.h b/thirdparty/fmt/include/fmt/base.h
index 627649425..9eeeb2ce7 100644
--- a/thirdparty/fmt/include/fmt/base.h
+++ b/thirdparty/fmt/include/fmt/base.h
@@ -15,15 +15,13 @@
#ifndef FMT_MODULE
# include // CHAR_BIT
# include // FILE
-# include // strlen
+# include // memcmp
-// is also included transitively from .
-# include // std::byte
# include // std::enable_if
#endif
// The fmt library version in the form major * 10000 + minor * 100 + patch.
-#define FMT_VERSION 110002
+#define FMT_VERSION 110103
// Detect compiler versions.
#if defined(__clang__) && !defined(__ibmxl__)
@@ -78,6 +76,11 @@
#else
# define FMT_HAS_INCLUDE(x) 0
#endif
+#ifdef __has_builtin
+# define FMT_HAS_BUILTIN(x) __has_builtin(x)
+#else
+# define FMT_HAS_BUILTIN(x) 0
+#endif
#ifdef __has_cpp_attribute
# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
@@ -93,9 +96,9 @@
// Detect C++14 relaxed constexpr.
#ifdef FMT_USE_CONSTEXPR
// Use the provided definition.
-#elif FMT_GCC_VERSION >= 600 && FMT_CPLUSPLUS >= 201402L
-// GCC only allows throw in constexpr since version 6:
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67371.
+#elif FMT_GCC_VERSION >= 702 && FMT_CPLUSPLUS >= 201402L
+// GCC only allows constexpr member functions in non-literal types since 7.2:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66297.
# define FMT_USE_CONSTEXPR 1
#elif FMT_ICC_VERSION
# define FMT_USE_CONSTEXPR 0 // https://github.com/fmtlib/fmt/issues/1628
@@ -138,40 +141,19 @@
# define FMT_CONSTEXPR20
#endif
-#if defined(FMT_USE_NONTYPE_TEMPLATE_ARGS)
-// Use the provided definition.
-#elif defined(__NVCOMPILER)
-# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
-#elif FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L
-# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
-#elif defined(__cpp_nontype_template_args) && \
- __cpp_nontype_template_args >= 201911L
-# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
-#elif FMT_CLANG_VERSION >= 1200 && FMT_CPLUSPLUS >= 202002L
-# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
-#else
-# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
-#endif
-
-#ifdef FMT_USE_CONCEPTS
-// Use the provided definition.
-#elif defined(__cpp_concepts)
-# define FMT_USE_CONCEPTS 1
-#else
-# define FMT_USE_CONCEPTS 0
-#endif
-
// Check if exceptions are disabled.
-#ifdef FMT_EXCEPTIONS
+#ifdef FMT_USE_EXCEPTIONS
// Use the provided definition.
#elif defined(__GNUC__) && !defined(__EXCEPTIONS)
-# define FMT_EXCEPTIONS 0
+# define FMT_USE_EXCEPTIONS 0
+#elif defined(__clang__) && !defined(__cpp_exceptions)
+# define FMT_USE_EXCEPTIONS 0
#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS
-# define FMT_EXCEPTIONS 0
+# define FMT_USE_EXCEPTIONS 0
#else
-# define FMT_EXCEPTIONS 1
+# define FMT_USE_EXCEPTIONS 1
#endif
-#if FMT_EXCEPTIONS
+#if FMT_USE_EXCEPTIONS
# define FMT_TRY try
# define FMT_CATCH(x) catch (x)
#else
@@ -179,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__)
@@ -197,12 +193,12 @@
# define FMT_NORETURN
#endif
-#ifndef FMT_NODISCARD
-# if FMT_HAS_CPP17_ATTRIBUTE(nodiscard)
-# define FMT_NODISCARD [[nodiscard]]
-# else
-# define FMT_NODISCARD
-# endif
+#ifdef FMT_NODISCARD
+// Use the provided definition.
+#elif FMT_HAS_CPP17_ATTRIBUTE(nodiscard)
+# define FMT_NODISCARD [[nodiscard]]
+#else
+# define FMT_NODISCARD
#endif
#ifdef FMT_DEPRECATED
@@ -213,14 +209,14 @@
# define FMT_DEPRECATED /* deprecated */
#endif
-#ifdef FMT_INLINE
+#ifdef FMT_ALWAYS_INLINE
// Use the provided definition.
#elif FMT_GCC_VERSION || FMT_CLANG_VERSION
# define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
#else
# define FMT_ALWAYS_INLINE inline
#endif
-// A version of FMT_INLINE to prevent code bloat in debug mode.
+// A version of FMT_ALWAYS_INLINE to prevent code bloat in debug mode.
#ifdef NDEBUG
# define FMT_INLINE FMT_ALWAYS_INLINE
#else
@@ -233,30 +229,24 @@
# define FMT_VISIBILITY(value)
#endif
-#ifndef FMT_GCC_PRAGMA
+// Detect pragmas.
+#define FMT_PRAGMA_IMPL(x) _Pragma(#x)
+#if FMT_GCC_VERSION >= 504 && !defined(__NVCOMPILER)
// Workaround a _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884
// and an nvhpc warning: https://github.com/fmtlib/fmt/pull/2582.
-# if FMT_GCC_VERSION >= 504 && !defined(__NVCOMPILER)
-# define FMT_GCC_PRAGMA(arg) _Pragma(arg)
-# else
-# define FMT_GCC_PRAGMA(arg)
-# endif
+# define FMT_PRAGMA_GCC(x) FMT_PRAGMA_IMPL(GCC x)
+#else
+# define FMT_PRAGMA_GCC(x)
#endif
-
-// GCC < 5 requires this-> in decltype.
-#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
-# define FMT_DECLTYPE_THIS this->
+#if FMT_CLANG_VERSION
+# define FMT_PRAGMA_CLANG(x) FMT_PRAGMA_IMPL(clang x)
#else
-# define FMT_DECLTYPE_THIS
+# define FMT_PRAGMA_CLANG(x)
#endif
-
#if FMT_MSC_VERSION
# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__))
-# define FMT_UNCHECKED_ITERATOR(It) \
- using _Unchecked_type = It // Mark iterator as checked.
#else
# define FMT_MSC_WARNING(...)
-# define FMT_UNCHECKED_ITERATOR(It) using unchecked_type = It
#endif
#ifndef FMT_BEGIN_NAMESPACE
@@ -274,7 +264,13 @@
# define FMT_END_EXPORT
#endif
-#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
+#ifdef _WIN32
+# define FMT_WIN32 1
+#else
+# define FMT_WIN32 0
+#endif
+
+#if !defined(FMT_HEADER_ONLY) && FMT_WIN32
# if defined(FMT_LIB_EXPORT)
# define FMT_API __declspec(dllexport)
# elif defined(FMT_SHARED)
@@ -287,28 +283,26 @@
# define FMT_API
#endif
-#ifndef FMT_UNICODE
-# define FMT_UNICODE 1
+#ifndef FMT_OPTIMIZE_SIZE
+# define FMT_OPTIMIZE_SIZE 0
#endif
-// Check if rtti is available.
-#ifndef FMT_USE_RTTI
-// __RTTI is for EDG compilers. _CPPRTTI is for MSVC.
-# if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \
- defined(__INTEL_RTTI__) || defined(__RTTI)
-# define FMT_USE_RTTI 1
-# else
-# define FMT_USE_RTTI 0
-# endif
+// FMT_BUILTIN_TYPE=0 may result in smaller library size at the cost of higher
+// per-call binary size by passing built-in types through the extension API.
+#ifndef FMT_BUILTIN_TYPES
+# define FMT_BUILTIN_TYPES 1
#endif
-#define FMT_FWD(...) static_cast(__VA_ARGS__)
+#define FMT_APPLY_VARIADIC(expr) \
+ using ignore = int[]; \
+ (void)ignore { 0, (expr, 0)... }
// Enable minimal optimizations for more compact code in debug mode.
-FMT_GCC_PRAGMA("GCC push_options")
-#if !defined(__OPTIMIZE__) && !defined(__CUDACC__)
-FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
+FMT_PRAGMA_GCC(push_options)
+#if !defined(__OPTIMIZE__) && !defined(__CUDACC__) && !defined(FMT_MODULE)
+FMT_PRAGMA_GCC(optimize("Og"))
#endif
+FMT_PRAGMA_CLANG(diagnostic push)
FMT_BEGIN_NAMESPACE
@@ -324,17 +318,15 @@ template
using remove_const_t = typename std::remove_const::type;
template
using remove_cvref_t = typename std::remove_cv>::type;
-template struct type_identity {
- using type = T;
-};
-template using type_identity_t = typename type_identity::type;
template
using make_unsigned_t = typename std::make_unsigned::type;
template
using underlying_t = typename std::underlying_type::type;
+template using decay_t = typename std::decay::type;
+using nullptr_t = decltype(nullptr);
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
-// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
+// A workaround for gcc 4.9 to make void_t work in a SFINAE context.
template struct void_t_impl {
using type = void;
};
@@ -356,14 +348,12 @@ struct monostate {
# define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0
#endif
-// This is defined in base.h instead of format.h to avoid injecting in std.
-// It is a template to avoid undesirable implicit conversions to std::byte.
-#ifdef __cpp_lib_byte
-template ::value)>
-inline auto format_as(T b) -> unsigned char {
- return static_cast(b);
+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;
}
-#endif
namespace detail {
// Suppresses "unused variable" warnings with the method described in
@@ -373,9 +363,8 @@ template FMT_CONSTEXPR void ignore_unused(const T&...) {}
constexpr auto is_constant_evaluated(bool default_value = false) noexcept
-> bool {
-// Workaround for incompatibility between libstdc++ consteval-based
-// std::is_constant_evaluated() implementation and clang-14:
-// https://github.com/fmtlib/fmt/issues/3247.
+// Workaround for incompatibility between clang 14 and libstdc++ consteval-based
+// std::is_constant_evaluated: https://github.com/fmtlib/fmt/issues/3247.
#if FMT_CPLUSPLUS >= 202002L && FMT_GLIBCXX_RELEASE >= 12 && \
(FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500)
ignore_unused(default_value);
@@ -389,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);
@@ -408,15 +399,14 @@ FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
#endif
#ifdef FMT_USE_INT128
-// Do nothing.
+// Use the provided definition.
#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \
!(FMT_CLANG_VERSION && FMT_MSC_VERSION)
# define FMT_USE_INT128 1
using int128_opt = __int128_t; // An optional native 128-bit integer.
using uint128_opt = __uint128_t;
-template inline auto convert_for_visit(T value) -> T {
- return value;
-}
+inline auto map(int128_opt x) -> int128_opt { return x; }
+inline auto map(uint128_opt x) -> uint128_opt { return x; }
#else
# define FMT_USE_INT128 0
#endif
@@ -424,9 +414,23 @@ template inline auto convert_for_visit(T value) -> T {
enum class int128_opt {};
enum class uint128_opt {};
// Reduce template instantiations.
-template auto convert_for_visit(T) -> monostate { return {}; }
+inline auto map(int128_opt) -> monostate { return {}; }
+inline auto map(uint128_opt) -> monostate { return {}; }
+#endif
+
+#ifndef FMT_USE_BITINT
+# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500)
#endif
+#if FMT_USE_BITINT
+FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension")
+template using bitint = _BitInt(N);
+template using ubitint = unsigned _BitInt(N);
+#else
+template struct bitint {};
+template struct ubitint {};
+#endif // FMT_USE_BITINT
+
// Casts a nonnegative integer to unsigned.
template
FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t {
@@ -434,6 +438,9 @@ FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t {
return static_cast>(value);
}
+template
+using unsigned_char = conditional_t;
+
// A heuristic to detect std::string and std::[experimental::]string_view.
// It is mainly used to avoid dependency on <[experimental/]string_view>.
template
@@ -444,25 +451,19 @@ struct is_std_string_like().find_first_of(
: std::is_convertible().data()),
const typename T::value_type*> {};
-// Returns true iff the literal encoding is UTF-8.
-constexpr auto is_utf8_enabled() -> bool {
- // Avoid an MSVC sign extension bug: https://github.com/fmtlib/fmt/pull/2297.
- using uchar = unsigned char;
- return sizeof("\u00A7") == 3 && uchar("\u00A7"[0]) == 0xC2 &&
- uchar("\u00A7"[1]) == 0xA7;
-}
-constexpr auto use_utf8() -> bool {
- return !FMT_MSC_VERSION || is_utf8_enabled();
-}
+// Check if the literal encoding is UTF-8.
+enum { is_utf8_enabled = "\u00A7"[1] == '\xA7' };
+enum { use_utf8 = !FMT_WIN32 || is_utf8_enabled };
+
+#ifndef FMT_UNICODE
+# define FMT_UNICODE 1
+#endif
-static_assert(!FMT_UNICODE || use_utf8(),
+static_assert(!FMT_UNICODE || use_utf8,
"Unicode support requires compiling with /utf-8");
-template FMT_CONSTEXPR auto length(const Char* s) -> size_t {
- size_t len = 0;
- while (*s++) ++len;
- return len;
-}
+template constexpr const char* narrow(const T*) { return nullptr; }
+constexpr FMT_ALWAYS_INLINE const char* narrow(const char* s) { return s; }
template
FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n)
@@ -494,17 +495,18 @@ struct is_back_insert_iterator<
// Extracts a reference to the container from *insert_iterator.
template
-inline auto get_container(OutputIt it) -> typename OutputIt::container_type& {
+inline FMT_CONSTEXPR20 auto get_container(OutputIt it) ->
+ typename OutputIt::container_type& {
struct accessor : OutputIt {
- accessor(OutputIt base) : OutputIt(base) {}
+ FMT_CONSTEXPR20 accessor(OutputIt base) : OutputIt(base) {}
using OutputIt::container;
};
return *accessor(it).container;
}
} // namespace detail
-// Checks whether T is a container with contiguous storage.
-template struct is_contiguous : std::false_type {};
+// Parsing-related public API and forward declarations.
+FMT_BEGIN_EXPORT
/**
* An implementation of `std::basic_string_view` for pre-C++17. It provides a
@@ -513,7 +515,6 @@ template struct is_contiguous : std::false_type {};
* compiled with a different `-std` option than the client code (which is not
* recommended).
*/
-FMT_EXPORT
template class basic_string_view {
private:
const Char* data_;
@@ -529,16 +530,23 @@ template class basic_string_view {
constexpr basic_string_view(const Char* s, size_t count) noexcept
: data_(s), size_(count) {}
- constexpr basic_string_view(std::nullptr_t) = delete;
+ constexpr basic_string_view(nullptr_t) = delete;
/// Constructs a string reference object from a C string.
- FMT_CONSTEXPR20
- basic_string_view(const Char* s)
- : data_(s),
- size_(detail::const_check(std::is_same::value &&
- !detail::is_constant_evaluated(false))
- ? strlen(reinterpret_cast(s))
- : detail::length(s)) {}
+#if FMT_GCC_VERSION
+ FMT_ALWAYS_INLINE
+#endif
+ FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) {
+#if FMT_HAS_BUILTIN(__buitin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION
+ if (std::is_same::value) {
+ size_ = __builtin_strlen(detail::narrow(s));
+ return;
+ }
+#endif
+ size_t len = 0;
+ while (*s++) ++len;
+ size_ = len;
+ }
/// Constructs a string reference from a `std::basic_string` or a
/// `std::basic_string_view` object.
@@ -579,11 +587,10 @@ 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);
- if (result == 0)
- result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
- return result;
+ 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);
}
FMT_CONSTEXPR friend auto operator==(basic_string_view lhs,
@@ -607,14 +614,315 @@ template class basic_string_view {
}
};
-FMT_EXPORT
using string_view = basic_string_view;
-/// Specifies if `T` is a character type. Can be specialized by users.
-FMT_EXPORT
-template struct is_char : std::false_type {};
+/// Specifies if `T` is an extended character type. Can be specialized by users.
+template struct is_xchar : std::false_type {};
+template <> struct is_xchar : std::true_type {};
+template <> struct is_xchar : std::true_type {};
+template <> struct is_xchar : std::true_type {};
+#ifdef __cpp_char8_t
+template <> struct is_xchar : std::true_type {};
+#endif
+
+// DEPRECATED! Will be replaced with an alias to prevent specializations.
+template struct is_char : is_xchar {};
template <> struct is_char : std::true_type {};
+template class basic_appender;
+using appender = basic_appender;
+
+// Checks whether T is a container with contiguous storage.
+template struct is_contiguous : std::false_type {};
+
+class context;
+template class generic_context;
+template class parse_context;
+
+// Longer aliases for C++20 compatibility.
+template using basic_format_parse_context = parse_context;
+using format_parse_context = parse_context;
+template
+using basic_format_context =
+ conditional_t::value, context,
+ generic_context>;
+using format_context = context;
+
+template
+using buffered_context =
+ conditional_t::value, context,
+ generic_context, Char>>;
+
+template class basic_format_arg;
+template class basic_format_args;
+
+// A separate type would result in shorter symbols but break ABI compatibility
+// between clang and gcc on ARM (#1919).
+using format_args = basic_format_args;
+
+// A formatter for objects of type T.
+template
+struct formatter {
+ // A deleted default constructor indicates a disabled formatter.
+ formatter() = delete;
+};
+
+/// Reports a format error at compile time or, via a `format_error` exception,
+/// at runtime.
+// This function is intentionally not constexpr to give a compile-time error.
+FMT_NORETURN FMT_API void report_error(const char* message);
+
+enum class presentation_type : unsigned char {
+ // Common specifiers:
+ none = 0,
+ debug = 1, // '?'
+ string = 2, // 's' (string, bool)
+
+ // Integral, bool and character specifiers:
+ dec = 3, // 'd'
+ hex, // 'x' or 'X'
+ oct, // 'o'
+ bin, // 'b' or 'B'
+ chr, // 'c'
+
+ // String and pointer specifiers:
+ pointer = 3, // 'p'
+
+ // Floating-point specifiers:
+ exp = 1, // 'e' or 'E' (1 since there is no FP debug presentation)
+ fixed, // 'f' or 'F'
+ general, // 'g' or 'G'
+ hexfloat // 'a' or 'A'
+};
+
+enum class align { none, left, right, center, numeric };
+enum class sign { none, minus, plus, space };
+enum class arg_id_kind { none, index, name };
+
+// Basic format specifiers for built-in and string types.
+class basic_specs {
+ private:
+ // Data is arranged as follows:
+ //
+ // 0 1 2 3
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // |type |align| w | p | s |u|#|L| f | unused |
+ // +-----+-----+---+---+---+-+-+-+-----+---------------------------+
+ //
+ // w - dynamic width info
+ // p - dynamic precision info
+ // s - sign
+ // u - uppercase (e.g. 'X' for 'x')
+ // # - alternate form ('#')
+ // L - localized
+ // f - fill size
+ //
+ // Bitfields are not used because of compiler bugs such as gcc bug 61414.
+ enum : unsigned {
+ type_mask = 0x00007,
+ align_mask = 0x00038,
+ width_mask = 0x000C0,
+ precision_mask = 0x00300,
+ sign_mask = 0x00C00,
+ uppercase_mask = 0x01000,
+ alternate_mask = 0x02000,
+ localized_mask = 0x04000,
+ fill_size_mask = 0x38000,
+
+ align_shift = 3,
+ width_shift = 6,
+ precision_shift = 8,
+ sign_shift = 10,
+ fill_size_shift = 15,
+
+ max_fill_size = 4
+ };
+
+ unsigned data_ = 1 << fill_size_shift;
+ static_assert(sizeof(data_) * CHAR_BIT >= 18, "");
+
+ // Character (code unit) type is erased to prevent template bloat.
+ char fill_data_[max_fill_size] = {' '};
+
+ FMT_CONSTEXPR void set_fill_size(size_t size) {
+ data_ = (data_ & ~fill_size_mask) |
+ (static_cast(size) << fill_size_shift);
+ }
+
+ public:
+ constexpr auto type() const -> presentation_type {
+ return static_cast(data_ & type_mask);
+ }
+ FMT_CONSTEXPR void set_type(presentation_type t) {
+ data_ = (data_ & ~type_mask) | static_cast(t);
+ }
+
+ constexpr auto align() const -> align {
+ return static_cast((data_ & align_mask) >> align_shift);
+ }
+ FMT_CONSTEXPR void set_align(fmt::align a) {
+ data_ = (data_ & ~align_mask) | (static_cast(a) << align_shift);
+ }
+
+ constexpr auto dynamic_width() const -> arg_id_kind {
+ return static_cast((data_ & width_mask) >> width_shift);
+ }
+ FMT_CONSTEXPR void set_dynamic_width(arg_id_kind w) {
+ data_ = (data_ & ~width_mask) | (static_cast(w) << width_shift);
+ }
+
+ FMT_CONSTEXPR auto dynamic_precision() const -> arg_id_kind {
+ return static_cast((data_ & precision_mask) >>
+ precision_shift);
+ }
+ FMT_CONSTEXPR void set_dynamic_precision(arg_id_kind p) {
+ data_ = (data_ & ~precision_mask) |
+ (static_cast(p) << precision_shift);
+ }
+
+ constexpr bool dynamic() const {
+ return (data_ & (width_mask | precision_mask)) != 0;
+ }
+
+ constexpr auto sign() const -> sign {
+ return static_cast((data_ & sign_mask) >> sign_shift);
+ }
+ FMT_CONSTEXPR void set_sign(fmt::sign s) {
+ data_ = (data_ & ~sign_mask) | (static_cast(s) << sign_shift);
+ }
+
+ constexpr auto upper() const -> bool { return (data_ & uppercase_mask) != 0; }
+ FMT_CONSTEXPR void set_upper() { data_ |= uppercase_mask; }
+
+ constexpr auto alt() const -> bool { return (data_ & alternate_mask) != 0; }
+ FMT_CONSTEXPR void set_alt() { data_ |= alternate_mask; }
+ FMT_CONSTEXPR void clear_alt() { data_ &= ~alternate_mask; }
+
+ constexpr auto localized() const -> bool {
+ return (data_ & localized_mask) != 0;
+ }
+ FMT_CONSTEXPR void set_localized() { data_ |= localized_mask; }
+
+ constexpr auto fill_size() const -> size_t {
+ return (data_ & fill_size_mask) >> fill_size_shift;
+ }
+
+ template ::value)>
+ constexpr auto fill() const -> const Char* {
+ return fill_data_;
+ }
+ template ::value)>
+ constexpr auto fill() const -> const Char* {
+ return nullptr;
+ }
+
+ 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_[2]) << 16));
+ }
+
+ FMT_CONSTEXPR void set_fill(char c) {
+ fill_data_[0] = c;
+ set_fill_size(1);
+ }
+
+ template
+ FMT_CONSTEXPR void set_fill(basic_string_view s) {
+ auto size = s.size();
+ set_fill_size(size);
+ if (size == 1) {
+ 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 copy_fill_from(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.
+struct format_specs : basic_specs {
+ int width;
+ int precision;
+
+ constexpr format_specs() : width(0), precision(-1) {}
+};
+
+/**
+ * Parsing context consisting of a format string range being parsed and an
+ * argument counter for automatic indexing.
+ */
+template class parse_context {
+ private:
+ basic_string_view fmt_;
+ int next_arg_id_;
+
+ enum { use_constexpr_cast = !FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200 };
+
+ FMT_CONSTEXPR void do_check_arg_id(int arg_id);
+
+ public:
+ using char_type = Char;
+ using iterator = const Char*;
+
+ constexpr explicit parse_context(basic_string_view fmt,
+ int next_arg_id = 0)
+ : fmt_(fmt), next_arg_id_(next_arg_id) {}
+
+ /// Returns an iterator to the beginning of the format string range being
+ /// parsed.
+ constexpr auto begin() const noexcept -> iterator { return fmt_.begin(); }
+
+ /// Returns an iterator past the end of the format string range being parsed.
+ constexpr auto end() const noexcept -> iterator { return fmt_.end(); }
+
+ /// Advances the begin iterator to `it`.
+ FMT_CONSTEXPR void advance_to(iterator it) {
+ fmt_.remove_prefix(detail::to_unsigned(it - begin()));
+ }
+
+ /// Reports an error if using the manual argument indexing; otherwise returns
+ /// the next argument index and switches to the automatic indexing.
+ FMT_CONSTEXPR auto next_arg_id() -> int {
+ if (next_arg_id_ < 0) {
+ report_error("cannot switch from manual to automatic argument indexing");
+ return 0;
+ }
+ int id = next_arg_id_++;
+ do_check_arg_id(id);
+ return id;
+ }
+
+ /// Reports an error if using the automatic argument indexing; otherwise
+ /// switches to the manual indexing.
+ FMT_CONSTEXPR void check_arg_id(int id) {
+ if (next_arg_id_ > 0) {
+ report_error("cannot switch from automatic to manual argument indexing");
+ return;
+ }
+ next_arg_id_ = -1;
+ do_check_arg_id(id);
+ }
+ FMT_CONSTEXPR void check_arg_id(basic_string_view) {
+ next_arg_id_ = -1;
+ }
+ FMT_CONSTEXPR void check_dynamic_spec(int arg_id);
+};
+
+FMT_END_EXPORT
+
namespace detail {
// Constructs fmt::basic_string_view from types implicitly convertible
@@ -643,16 +951,10 @@ struct has_to_string_view<
T, void_t()))>>
: std::true_type {};
-template struct string_literal {
- static constexpr Char value[sizeof...(C)] = {C...};
- constexpr operator basic_string_view() const {
- return {value, sizeof...(C)};
- }
-};
-#if FMT_CPLUSPLUS < 201703L
-template
-constexpr Char string_literal::value[sizeof...(C)];
-#endif
+/// String's character (code unit) type. detail:: is intentional to prevent ADL.
+template ()))>
+using char_t = typename V::value_type;
enum class type {
none_type,
@@ -727,103 +1029,196 @@ enum {
cstring_set = set(type::cstring_type),
pointer_set = set(type::pointer_type)
};
-} // namespace detail
-
-/// Reports a format error at compile time or, via a `format_error` exception,
-/// at runtime.
-// This function is intentionally not constexpr to give a compile-time error.
-FMT_NORETURN FMT_API void report_error(const char* message);
-FMT_DEPRECATED FMT_NORETURN inline void throw_format_error(
- const char* message) {
- report_error(message);
-}
+struct view {};
-/// String's character (code unit) type.
-template ()))>
-using char_t = typename V::value_type;
+template struct named_arg;
+template struct is_named_arg : std::false_type {};
+template struct is_static_named_arg : std::false_type {};
-/**
- * Parsing context consisting of a format string range being parsed and an
- * argument counter for automatic indexing.
- * You can use the `format_parse_context` type alias for `char` instead.
- */
-FMT_EXPORT
-template class basic_format_parse_context {
- private:
- basic_string_view format_str_;
- int next_arg_id_;
+template
+struct is_named_arg> : std::true_type {};
- FMT_CONSTEXPR void do_check_arg_id(int id);
+template struct named_arg : view {
+ const Char* name;
+ const T& value;
- public:
- using char_type = Char;
- using iterator = const Char*;
+ named_arg(const Char* n, const T& v) : name(n), value(v) {}
+ static_assert(!is_named_arg::value, "nested named arguments");
+};
- explicit constexpr basic_format_parse_context(
- basic_string_view format_str, int next_arg_id = 0)
- : format_str_(format_str), next_arg_id_(next_arg_id) {}
+template constexpr auto count() -> int { return B ? 1 : 0; }
+template constexpr auto count() -> int {
+ return (B1 ? 1 : 0) + count();
+}
- /// Returns an iterator to the beginning of the format string range being
- /// parsed.
- constexpr auto begin() const noexcept -> iterator {
- return format_str_.begin();
- }
+template constexpr auto count_named_args() -> int {
+ return count::value...>();
+}
+template constexpr auto count_static_named_args() -> int {
+ return count::value...>();
+}
- /// Returns an iterator past the end of the format string range being parsed.
- constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
+template struct named_arg_info {
+ const Char* name;
+ int id;
+};
- /// Advances the begin iterator to `it`.
- FMT_CONSTEXPR void advance_to(iterator it) {
- format_str_.remove_prefix(detail::to_unsigned(it - begin()));
- }
+template ::value)>
+void init_named_arg(named_arg_info*, int& arg_index, int&, const T&) {
+ ++arg_index;
+}
+template ::value)>
+void init_named_arg(named_arg_info* named_args, int& arg_index,
+ int& named_arg_index, const T& arg) {
+ named_args[named_arg_index++] = {arg.name, arg_index++};
+}
- /// Reports an error if using the manual argument indexing; otherwise returns
- /// the next argument index and switches to the automatic indexing.
- FMT_CONSTEXPR auto next_arg_id() -> int {
- if (next_arg_id_ < 0) {
- report_error("cannot switch from manual to automatic argument indexing");
- return 0;
- }
- int id = next_arg_id_++;
- do_check_arg_id(id);
- return id;
- }
+template ::value)>
+FMT_CONSTEXPR void init_static_named_arg(named_arg_info*, int& arg_index,
+ int&) {
+ ++arg_index;
+}
+template ::value)>
+FMT_CONSTEXPR void init_static_named_arg(named_arg_info* named_args,
+ int& arg_index, int& named_arg_index) {
+ named_args[named_arg_index++] = {T::name, arg_index++};
+}
- /// Reports an error if using the automatic argument indexing; otherwise
- /// switches to the manual indexing.
- FMT_CONSTEXPR void check_arg_id(int id) {
- if (next_arg_id_ > 0) {
- report_error("cannot switch from automatic to manual argument indexing");
- return;
- }
- next_arg_id_ = -1;
- do_check_arg_id(id);
- }
- FMT_CONSTEXPR void check_arg_id(basic_string_view) {
- next_arg_id_ = -1;
- }
- FMT_CONSTEXPR void check_dynamic_spec(int arg_id);
+// To minimize the number of types we need to deal with, long is translated
+// either to int or to long long depending on its size.
+enum { long_short = sizeof(long) == sizeof(int) };
+using long_type = conditional_t;
+using ulong_type = conditional_t;
+
+template
+using format_as_result =
+ remove_cvref_t()))>;
+template
+using format_as_member_result =
+ remove_cvref_t::format_as(std::declval()))>;
+
+template
+struct use_format_as : std::false_type {};
+// format_as member is only used to avoid injection into the std namespace.
+template
+struct use_format_as_member : std::false_type {};
+
+// Only map owning types because mapping views can be unsafe.
+template
+struct use_format_as<
+ T, bool_constant>::value>>
+ : std::true_type {};
+template
+struct use_format_as_member<
+ T, bool_constant>::value>>
+ : std::true_type {};
+
+template >
+using use_formatter =
+ bool_constant<(std::is_class::value || std::is_enum::value ||
+ std::is_union::value || std::is_array::value) &&
+ !has_to_string_view::value && !is_named_arg::value &&
+ !use_format_as::value && !use_format_as_member::value>;
+
+template >
+auto has_formatter_impl(T* p, buffered_context* ctx = nullptr)
+ -> decltype(formatter().format(*p, *ctx), std::true_type());
+template auto has_formatter_impl(...) -> std::false_type;
+
+// T can be const-qualified to check if it is const-formattable.
+template constexpr auto has_formatter() -> bool {
+ return decltype(has_formatter_impl(static_cast(nullptr)))::value;
+}
+
+// Maps formatting argument types to natively supported types or user-defined
+// types with formatters. Returns void on errors to be SFINAE-friendly.
+template struct type_mapper {
+ static auto map(signed char) -> int;
+ static auto map(unsigned char) -> unsigned;
+ static auto map(short) -> int;
+ static auto map(unsigned short) -> unsigned;
+ static auto map(int) -> int;
+ static auto map(unsigned) -> unsigned;
+ static auto map(long) -> long_type;
+ static auto map(unsigned long) -> ulong_type;
+ static auto map(long long) -> long long;
+ static auto map(unsigned long long) -> unsigned long long;
+ static auto map(int128_opt) -> int128_opt;
+ static auto map(uint128_opt) -> uint128_opt;
+ static auto map(bool) -> bool;
+
+ template
+ static auto map(bitint) -> conditional_t;
+ template
+ static auto map(ubitint)
+ -> conditional_t;
+
+ template ::value)>
+ static auto map(T) -> conditional_t<
+ std::is_same::value || std::is_same::value, Char, void>;
+
+ static auto map(float) -> float;
+ static auto map(double) -> double;
+ static auto map(long double) -> long double;
+
+ static auto map(Char*) -> const Char*;
+ static auto map(const Char*) -> const Char*;
+ template ,
+ FMT_ENABLE_IF(!std::is_pointer::value)>
+ static auto map(const T&) -> conditional_t::value,
+ basic_string_view, void>;
+
+ static auto map(void*) -> const void*;
+ static auto map(const void*) -> const void*;
+ static auto map(volatile void*) -> const void*;
+ static auto map(const volatile void*) -> const void*;
+ static auto map(nullptr_t) -> const void*;
+ template ::value ||
+ std::is_member_pointer::value)>
+ static auto map(const T&) -> void;
+
+ template ::value)>
+ static auto map(const T& x) -> decltype(map(format_as(x)));
+ template ::value)>
+ static auto map(const T& x) -> decltype(map(formatter::format_as(x)));
+
+ template ::value)>
+ static auto map(T&) -> conditional_t(), T&, void>;
+
+ template ::value)>
+ static auto map(const T& named_arg) -> decltype(map(named_arg.value));
};
-FMT_EXPORT
-using format_parse_context = basic_format_parse_context;
+// detail:: is used to workaround a bug in MSVC 2017.
+template
+using mapped_t = decltype(detail::type_mapper::map(std::declval()));
-namespace detail {
+// A type constant after applying type_mapper.
+template
+using mapped_type_constant = type_constant, Char>;
+
+template ::value>
+using stored_type_constant = std::integral_constant<
+ type, Context::builtin_types || TYPE == type::int_type ? TYPE
+ : type::custom_type>;
// A parse context with extra data used only in compile-time checks.
template
-class compile_parse_context : public basic_format_parse_context {
+class compile_parse_context : public parse_context {
private:
int num_args_;
const type* types_;
- using base = basic_format_parse_context;
+ using base = parse_context;
public:
- explicit FMT_CONSTEXPR compile_parse_context(
- basic_string_view format_str, int num_args, const type* types,
- int next_arg_id = 0)
- : base(format_str, next_arg_id), num_args_(num_args), types_(types) {}
+ 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) {}
constexpr auto num_args() const -> int { return num_args_; }
constexpr auto arg_type(int id) const -> type { return types_[id]; }
@@ -841,90 +1236,570 @@ class compile_parse_context : public basic_format_parse_context