summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <egor@tensin.name>2026-06-13 15:42:15 +0200
committerEgor Tensin <egor@tensin.name>2026-06-13 15:42:15 +0200
commit80452ac0abc6494000a9bbad8d7dccfd72ea85f2 (patch)
tree2d46252837083d1d2cfe0aa25d63aa23dfe80714
parentworkflows/ci: add clang-format job (diff)
downloadaes-tools-80452ac0abc6494000a9bbad8d7dccfd72ea85f2.tar.gz
aes-tools-80452ac0abc6494000a9bbad8d7dccfd72ea85f2.zip
aesxx: upgrade to std::string_view, std::format & <filesystem>
-rw-r--r--aesxx/CMakeLists.txt3
-rw-r--r--aesxx/include/aesxx/aes.hpp25
-rw-r--r--aesxx/include/aesxx/api.hpp15
-rw-r--r--aesxx/include/aesxx/box.hpp29
-rw-r--r--aesxx/include/aesxx/debug.hpp25
-rw-r--r--aesxx/include/aesxx/error.hpp5
-rw-r--r--aesxx/utils/CMakeLists.txt3
-rw-r--r--aesxx/utils/block_cmd_parser.hpp3
-rw-r--r--aesxx/utils/block_dumper.hpp14
-rw-r--r--aesxx/utils/block_input.hpp5
-rw-r--r--aesxx/utils/decrypt_block.cpp7
-rw-r--r--aesxx/utils/decrypt_bmp.cpp3
-rw-r--r--aesxx/utils/decrypt_file.cpp3
-rw-r--r--aesxx/utils/encrypt_block.cpp7
-rw-r--r--aesxx/utils/encrypt_bmp.cpp3
-rw-r--r--aesxx/utils/encrypt_file.cpp3
-rw-r--r--aesxx/utils/file_cmd_parser.hpp3
-rw-r--r--aesxx/utils/helpers/command_line.hpp14
18 files changed, 78 insertions, 92 deletions
diff --git a/aesxx/CMakeLists.txt b/aesxx/CMakeLists.txt
index 378bad7..338ecef 100644
--- a/aesxx/CMakeLists.txt
+++ b/aesxx/CMakeLists.txt
@@ -1,3 +1,6 @@
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
find_package(Boost CONFIG REQUIRED)
add_library(aesxx INTERFACE)
diff --git a/aesxx/include/aesxx/aes.hpp b/aesxx/include/aesxx/aes.hpp
index c3457c8..dedd366 100644
--- a/aesxx/include/aesxx/aes.hpp
+++ b/aesxx/include/aesxx/aes.hpp
@@ -14,6 +14,7 @@
#include <cstddef>
#include <string>
+#include <string_view>
namespace aes {
namespace aes128 {
@@ -37,8 +38,8 @@ inline std::size_t get_number_of_rounds<AES_AES128>() {
}
template <>
-inline void from_string<AES_AES128>(aes128::Block& dest, const char* src) {
- aes_AES128_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{});
+inline void from_string<AES_AES128>(aes128::Block& dest, std::string_view src) {
+ aes_AES128_parse_block(&dest, src.data(), ErrorDetailsThrowsInDestructor{});
}
template <>
@@ -56,8 +57,8 @@ inline std::string to_matrix_string<AES_AES128>(const aes128::Block& src) {
}
template <>
-inline void from_string<AES_AES128>(aes128::Key& dest, const char* src) {
- aes_AES128_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{});
+inline void from_string<AES_AES128>(aes128::Key& dest, std::string_view src) {
+ aes_AES128_parse_key(&dest, src.data(), ErrorDetailsThrowsInDestructor{});
}
template <>
@@ -110,8 +111,8 @@ inline std::size_t get_number_of_rounds<AES_AES192>() {
}
template <>
-inline void from_string<AES_AES192>(aes192::Block& dest, const char* src) {
- aes_AES192_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{});
+inline void from_string<AES_AES192>(aes192::Block& dest, std::string_view src) {
+ aes_AES192_parse_block(&dest, src.data(), ErrorDetailsThrowsInDestructor{});
}
template <>
@@ -129,8 +130,8 @@ inline std::string to_matrix_string<AES_AES192>(const aes192::Block& src) {
}
template <>
-inline void from_string<AES_AES192>(aes192::Key& dest, const char* src) {
- aes_AES192_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{});
+inline void from_string<AES_AES192>(aes192::Key& dest, std::string_view src) {
+ aes_AES192_parse_key(&dest, src.data(), ErrorDetailsThrowsInDestructor{});
}
template <>
@@ -183,8 +184,8 @@ inline std::size_t get_number_of_rounds<AES_AES256>() {
}
template <>
-inline void from_string<AES_AES256>(aes256::Block& dest, const char* src) {
- aes_AES256_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{});
+inline void from_string<AES_AES256>(aes256::Block& dest, std::string_view src) {
+ aes_AES256_parse_block(&dest, src.data(), ErrorDetailsThrowsInDestructor{});
}
template <>
@@ -202,8 +203,8 @@ inline std::string to_matrix_string<AES_AES256>(const aes256::Block& src) {
}
template <>
-inline void from_string<AES_AES256>(aes256::Key& dest, const char* src) {
- aes_AES256_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{});
+inline void from_string<AES_AES256>(aes256::Key& dest, std::string_view src) {
+ aes_AES256_parse_key(&dest, src.data(), ErrorDetailsThrowsInDestructor{});
}
template <>
diff --git a/aesxx/include/aesxx/api.hpp b/aesxx/include/aesxx/api.hpp
index 759ff0c..4c1c868 100644
--- a/aesxx/include/aesxx/api.hpp
+++ b/aesxx/include/aesxx/api.hpp
@@ -10,6 +10,7 @@
#include <cstddef>
#include <string>
+#include <string_view>
#include <type_traits>
namespace aes {
@@ -21,12 +22,7 @@ template <Algorithm algorithm>
std::size_t get_number_of_rounds();
template <Algorithm algorithm>
-void from_string(typename Types<algorithm>::Block&, const char*);
-
-template <Algorithm algorithm>
-void from_string(typename Types<algorithm>::Block& dest, const std::string& src) {
- from_string<algorithm>(dest, src.c_str());
-}
+void from_string(typename Types<algorithm>::Block&, std::string_view);
template <Algorithm algorithm>
std::string to_string(const typename Types<algorithm>::Block&);
@@ -35,12 +31,7 @@ template <Algorithm algorithm>
std::string to_matrix_string(const typename Types<algorithm>::Block&);
template <Algorithm algorithm>
-void from_string(typename Types<algorithm>::Key&, const char*);
-
-template <Algorithm algorithm>
-void from_string(typename Types<algorithm>::Key& dest, const std::string& src) {
- from_string<algorithm>(dest, src.c_str());
-}
+void from_string(typename Types<algorithm>::Key&, std::string_view);
template <Algorithm algorithm>
std::string to_string(const typename Types<algorithm>::Key&);
diff --git a/aesxx/include/aesxx/box.hpp b/aesxx/include/aesxx/box.hpp
index 540688b..fb42525 100644
--- a/aesxx/include/aesxx/box.hpp
+++ b/aesxx/include/aesxx/box.hpp
@@ -13,6 +13,7 @@
#include <cstddef>
#include <string>
+#include <string_view>
#include <vector>
namespace aes {
@@ -34,20 +35,12 @@ public:
return reinterpret_cast<const char*>(&str);
}
- static void parse_block(Block& dest, Algorithm algorithm, const char* src) {
- aes_box_parse_block(&dest, algorithm, src, ErrorDetailsThrowsInDestructor{});
+ static void parse_block(Block& dest, Algorithm algorithm, std::string_view src) {
+ aes_box_parse_block(&dest, algorithm, src.data(), ErrorDetailsThrowsInDestructor{});
}
- static void parse_block(Block& dest, Algorithm algorithm, const std::string& src) {
- parse_block(dest, algorithm, src.c_str());
- }
-
- static void parse_key(Key& dest, Algorithm algorithm, const char* src) {
- aes_box_parse_key(&dest, algorithm, src, ErrorDetailsThrowsInDestructor{});
- }
-
- static void parse_key(Key& dest, Algorithm algorithm, const std::string& src) {
- parse_key(dest, algorithm, src.c_str());
+ static void parse_key(Key& dest, Algorithm algorithm, std::string_view src) {
+ aes_box_parse_key(&dest, algorithm, src.data(), ErrorDetailsThrowsInDestructor{});
}
Box(Algorithm algorithm, const Key& key) : algorithm{algorithm}, mode{AES_ECB} {
@@ -115,22 +108,14 @@ public:
return format_key(src, get_algorithm());
}
- void parse_block(Block& dest, const char* src) {
+ void parse_block(Block& dest, std::string_view src) {
parse_block(dest, get_algorithm(), src);
}
- void parse_block(Block& dest, const std::string& src) {
- parse_block(dest, src.c_str());
- }
-
- void parse_key(Key& dest, const char* src) {
+ void parse_key(Key& dest, std::string_view src) {
parse_key(dest, get_algorithm(), src);
}
- void parse_key(Key& dest, const std::string& src) {
- parse_key(dest, src.c_str());
- }
-
Algorithm get_algorithm() const {
return algorithm;
}
diff --git a/aesxx/include/aesxx/debug.hpp b/aesxx/include/aesxx/debug.hpp
index d54605d..13ea898 100644
--- a/aesxx/include/aesxx/debug.hpp
+++ b/aesxx/include/aesxx/debug.hpp
@@ -13,8 +13,10 @@
#endif
#include <cstddef>
+#include <format>
#include <sstream>
#include <string>
+#include <string_view>
namespace aes {
namespace aux {
@@ -34,37 +36,28 @@ public:
private:
template <typename T>
static std::string put_between_brackets(const T& x) {
- std::ostringstream oss;
- oss << "[" << x << "]";
- return oss.str();
- }
-
- template <typename T>
- static std::string stringify(const T& x) {
- std::ostringstream oss;
- oss << x;
- return oss.str();
+ return std::format("[{}]", x);
}
static std::string format_address_fallback(const void* addr) {
return put_between_brackets(addr);
}
- static std::string format_module(const std::string& module_name, const void* offset = nullptr) {
+ static std::string format_module(std::string_view module_name, const void* offset = nullptr) {
if (offset == nullptr)
return put_between_brackets(module_name);
else
- return put_between_brackets(module_name + "+" + stringify(offset));
+ return put_between_brackets(std::format("{}+{}", module_name, offset));
}
- static std::string format_symbol(const std::string& symbol_name, const void* offset = nullptr) {
+ static std::string format_symbol(std::string_view symbol_name, const void* offset = nullptr) {
return format_module(symbol_name, offset);
}
- static std::string format_symbol(const std::string& module_name,
- const std::string& symbol_name,
+ static std::string format_symbol(std::string_view module_name,
+ std::string_view symbol_name,
const void* offset = nullptr) {
- return format_symbol(module_name + "!" + symbol_name, offset);
+ return format_symbol(std::format("{}!{}", module_name, symbol_name), offset);
}
#ifdef WIN32
diff --git a/aesxx/include/aesxx/error.hpp b/aesxx/include/aesxx/error.hpp
index e5c5803..72a50b3 100644
--- a/aesxx/include/aesxx/error.hpp
+++ b/aesxx/include/aesxx/error.hpp
@@ -14,6 +14,7 @@
#include <algorithm>
#include <cstdlib>
#include <cstring>
+#include <format>
#include <functional>
#include <ostream>
#include <stdexcept>
@@ -60,10 +61,10 @@ private:
};
inline std::ostream& operator<<(std::ostream& os, const Error& error) {
- os << "AES error: " << error.what() << '\n';
+ os << std::format("AES error: {}\n", error.what());
os << "Call stack:\n";
error.for_each_addr([&os](const void* addr, const std::string& name) {
- os << '\t' << addr << ' ' << name << '\n';
+ os << std::format("\t{} {}\n", addr, name);
});
return os;
}
diff --git a/aesxx/utils/CMakeLists.txt b/aesxx/utils/CMakeLists.txt
index 9ee06d0..de6c206 100644
--- a/aesxx/utils/CMakeLists.txt
+++ b/aesxx/utils/CMakeLists.txt
@@ -1,4 +1,4 @@
-find_package(Boost CONFIG REQUIRED COMPONENTS filesystem program_options)
+find_package(Boost CONFIG REQUIRED COMPONENTS program_options)
function(add_util name src)
set(target "util_${name}")
@@ -6,7 +6,6 @@ function(add_util name src)
target_link_libraries("${target}" PRIVATE
aesxx
Boost::disable_autolinking
- Boost::filesystem
Boost::program_options)
set_target_properties("${target}" PROPERTIES OUTPUT_NAME "${name}")
install(TARGETS "${target}" RUNTIME DESTINATION bin)
diff --git a/aesxx/utils/block_cmd_parser.hpp b/aesxx/utils/block_cmd_parser.hpp
index 3ae0eac..c179556 100644
--- a/aesxx/utils/block_cmd_parser.hpp
+++ b/aesxx/utils/block_cmd_parser.hpp
@@ -16,6 +16,7 @@
#include <deque>
#include <iterator>
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
@@ -29,7 +30,7 @@ public:
std::vector<Input> inputs;
- explicit BlockSettings(const std::string& argv0) : SettingsParser{argv0} {
+ explicit BlockSettings(std::string_view argv0) : SettingsParser{argv0} {
visible.add_options()(
"verbose,v", boost::program_options::bool_switch(&verbose), "enable verbose output");
visible.add_options()("algorithm,a",
diff --git a/aesxx/utils/block_dumper.hpp b/aesxx/utils/block_dumper.hpp
index 226ba20..c725670 100644
--- a/aesxx/utils/block_dumper.hpp
+++ b/aesxx/utils/block_dumper.hpp
@@ -8,13 +8,15 @@
#include <aesxx/all.hpp>
#include <cstdlib>
+#include <format>
#include <iostream>
+#include <string_view>
#include <type_traits>
template <aes::Algorithm algorithm>
-void dump_block(const char* header, const typename aes::Types<algorithm>::Block& block) {
- std::cout << header << ": " << aes::to_string<algorithm>(block) << "\n";
- std::cout << aes::to_matrix_string<algorithm>(block) << "\n";
+void dump_block(std::string_view header, const typename aes::Types<algorithm>::Block& block) {
+ std::cout << std::format("{}: {}\n", header, aes::to_string<algorithm>(block));
+ std::cout << std::format("{}\n", aes::to_matrix_string<algorithm>(block));
}
template <aes::Algorithm algorithm>
@@ -24,7 +26,7 @@ void dump_plaintext(const typename aes::Types<algorithm>::Block& block) {
template <aes::Algorithm algorithm>
void dump_key(const typename aes::Types<algorithm>::Key& key) {
- std::cout << "Key: " << aes::to_string<algorithm>(key) << "\n\n";
+ std::cout << std::format("Key: {}\n\n", aes::to_string<algorithm>(key));
}
template <aes::Algorithm algorithm>
@@ -40,9 +42,9 @@ void dump_iv(const typename aes::Types<algorithm>::Block& iv) {
template <aes::Algorithm algorithm>
void dump_round_keys(const char* header,
const typename aes::Types<algorithm>::RoundKeys& round_keys) {
- std::cout << header << ":\n";
+ std::cout << std::format("{}:\n", header);
for (std::size_t i = 0; i < aes::get_number_of_rounds<algorithm>(); ++i)
- std::cout << "\t[" << i << "]: " << aes::to_string<algorithm>(round_keys.keys[i]) << "\n";
+ std::cout << std::format("\t[{}]: {}\n", i, aes::to_string<algorithm>(round_keys.keys[i]));
std::cout << "\n";
}
diff --git a/aesxx/utils/block_input.hpp b/aesxx/utils/block_input.hpp
index 1dd3f70..042a680 100644
--- a/aesxx/utils/block_input.hpp
+++ b/aesxx/utils/block_input.hpp
@@ -6,15 +6,16 @@
#pragma once
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
class Input {
public:
- Input(const std::string& key, const std::string& iv, std::vector<std::string>&& blocks)
+ Input(std::string_view key, std::string_view iv, std::vector<std::string>&& blocks)
: key{key}, iv{iv}, blocks{std::move(blocks)} {}
- Input(const std::string& key, std::vector<std::string>&& blocks)
+ Input(std::string key, std::vector<std::string>&& blocks)
: key{key}, blocks{std::move(blocks)} {}
const std::string key;
diff --git a/aesxx/utils/decrypt_block.cpp b/aesxx/utils/decrypt_block.cpp
index 42e496e..d432e31 100644
--- a/aesxx/utils/decrypt_block.cpp
+++ b/aesxx/utils/decrypt_block.cpp
@@ -12,6 +12,7 @@
#include <boost/program_options.hpp>
#include <exception>
+#include <format>
#include <iostream>
#include <stdexcept>
#include <string>
@@ -48,7 +49,7 @@ void decrypt_with_mode(const Input& input, bool verbose = false) {
dump_plaintext<algorithm>(plaintext);
dump_next_iv<algorithm, mode>(decrypt);
} else {
- std::cout << aes::to_string<algorithm>(plaintext) << '\n';
+ std::cout << std::format("{}\n", aes::to_string<algorithm>(plaintext));
}
}
}
@@ -112,7 +113,7 @@ void decrypt_using_particular_box(aes::Box& box, const std::vector<std::string>&
aes::Box::Block plaintext;
box.decrypt_block(ciphertext, plaintext);
- std::cout << box.format_block(plaintext) << '\n';
+ std::cout << std::format("{}\n", box.format_block(plaintext));
}
}
@@ -161,7 +162,7 @@ int main(int argc, char** argv) {
std::cerr << e;
return 1;
} catch (const std::exception& e) {
- std::cerr << e.what() << "\n";
+ std::cerr << std::format("{}\n", e.what());
return 1;
}
return 0;
diff --git a/aesxx/utils/decrypt_bmp.cpp b/aesxx/utils/decrypt_bmp.cpp
index 86f6b7d..397ec02 100644
--- a/aesxx/utils/decrypt_bmp.cpp
+++ b/aesxx/utils/decrypt_bmp.cpp
@@ -14,6 +14,7 @@
#include <windows.h>
#include <exception>
+#include <format>
#include <iostream>
#include <string>
@@ -69,7 +70,7 @@ int main(int argc, char** argv) {
std::cerr << e;
return 1;
} catch (const std::exception& e) {
- std::cerr << e.what() << "\n";
+ std::cerr << std::format("{}\n", e.what());
return 1;
}
return 0;
diff --git a/aesxx/utils/decrypt_file.cpp b/aesxx/utils/decrypt_file.cpp
index 727362c..192f1f6 100644
--- a/aesxx/utils/decrypt_file.cpp
+++ b/aesxx/utils/decrypt_file.cpp
@@ -11,6 +11,7 @@
#include <boost/program_options.hpp>
#include <exception>
+#include <format>
#include <iostream>
#include <string>
#include <vector>
@@ -67,7 +68,7 @@ int main(int argc, char** argv) {
std::cerr << e;
return 1;
} catch (const std::exception& e) {
- std::cerr << e.what() << "\n";
+ std::cerr << std::format("{}\n", e.what());
return 1;
}
return 0;
diff --git a/aesxx/utils/encrypt_block.cpp b/aesxx/utils/encrypt_block.cpp
index b6bdca9..e132256 100644
--- a/aesxx/utils/encrypt_block.cpp
+++ b/aesxx/utils/encrypt_block.cpp
@@ -12,6 +12,7 @@
#include <boost/program_options.hpp>
#include <exception>
+#include <format>
#include <iostream>
#include <stdexcept>
#include <string>
@@ -48,7 +49,7 @@ void encrypt_with_mode(const Input& input, bool verbose = false) {
dump_ciphertext<algorithm>(ciphertext);
dump_next_iv<algorithm, mode>(encrypt);
} else {
- std::cout << aes::to_string<algorithm>(ciphertext) << '\n';
+ std::cout << std::format("{}\n", aes::to_string<algorithm>(ciphertext));
}
}
}
@@ -113,7 +114,7 @@ void encrypt_using_particular_box(aes::Box& box,
aes::Box::Block ciphertext;
box.encrypt_block(plaintext, ciphertext);
- std::cout << box.format_block(ciphertext) << '\n';
+ std::cout << std::format("{}\n", box.format_block(ciphertext));
}
}
@@ -162,7 +163,7 @@ int main(int argc, char** argv) {
std::cerr << e;
return 1;
} catch (const std::exception& e) {
- std::cerr << e.what() << "\n";
+ std::cerr << std::format("{}\n", e.what());
return 1;
}
return 0;
diff --git a/aesxx/utils/encrypt_bmp.cpp b/aesxx/utils/encrypt_bmp.cpp
index 01f3a78..5b74fb9 100644
--- a/aesxx/utils/encrypt_bmp.cpp
+++ b/aesxx/utils/encrypt_bmp.cpp
@@ -12,6 +12,7 @@
#include <boost/program_options.hpp>
#include <exception>
+#include <format>
#include <iostream>
#include <string>
@@ -67,7 +68,7 @@ int main(int argc, char** argv) {
std::cerr << e;
return 1;
} catch (const std::exception& e) {
- std::cerr << e.what() << "\n";
+ std::cerr << std::format("{}\n", e.what());
return 1;
}
return 0;
diff --git a/aesxx/utils/encrypt_file.cpp b/aesxx/utils/encrypt_file.cpp
index 4a774fd..2862bfb 100644
--- a/aesxx/utils/encrypt_file.cpp
+++ b/aesxx/utils/encrypt_file.cpp
@@ -11,6 +11,7 @@
#include <boost/program_options.hpp>
#include <exception>
+#include <format>
#include <iostream>
#include <string>
#include <vector>
@@ -67,7 +68,7 @@ int main(int argc, char** argv) {
std::cerr << e;
return 1;
} catch (const std::exception& e) {
- std::cerr << e.what() << "\n";
+ std::cerr << std::format("{}\n", e.what());
return 1;
}
return 0;
diff --git a/aesxx/utils/file_cmd_parser.hpp b/aesxx/utils/file_cmd_parser.hpp
index 4a504c8..2389d41 100644
--- a/aesxx/utils/file_cmd_parser.hpp
+++ b/aesxx/utils/file_cmd_parser.hpp
@@ -15,6 +15,7 @@
#include <ostream>
#include <string>
+#include <string_view>
#include <utility>
class FileSettings : public command_line::SettingsParser {
@@ -27,7 +28,7 @@ public:
std::string key;
std::string iv;
- explicit FileSettings(const std::string& argv0) : SettingsParser{argv0} {
+ explicit FileSettings(std::string_view argv0) : SettingsParser{argv0} {
visible.add_options()("algorithm,a",
boost::program_options::value<aes::Algorithm>(&algorithm)
->required()
diff --git a/aesxx/utils/helpers/command_line.hpp b/aesxx/utils/helpers/command_line.hpp
index 9a2da05..cc05a6a 100644
--- a/aesxx/utils/helpers/command_line.hpp
+++ b/aesxx/utils/helpers/command_line.hpp
@@ -5,19 +5,21 @@
#pragma once
-#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <exception>
+#include <filesystem>
+#include <format>
#include <iostream>
#include <ostream>
#include <string>
+#include <string_view>
namespace command_line {
class SettingsParser {
public:
- explicit SettingsParser(const std::string& argv0) : prog_name{extract_filename(argv0)} {
+ explicit SettingsParser(std::string_view argv0) : prog_name{extract_filename(argv0)} {
visible.add_options()("help,h", "show this message and exit");
}
@@ -49,7 +51,7 @@ public:
}
void usage_error(const std::exception& e) const {
- std::cerr << "usage error: " << e.what() << '\n';
+ std::cerr << std::format("usage error: {}\n", e.what());
std::cerr << *this;
}
@@ -59,15 +61,15 @@ protected:
boost::program_options::positional_options_description positional;
private:
- static std::string extract_filename(const std::string& path) {
- return boost::filesystem::path{path}.filename().string();
+ static std::string extract_filename(std::string_view path) {
+ return std::filesystem::path{path}.filename().string();
}
const std::string prog_name;
friend std::ostream& operator<<(std::ostream& os, const SettingsParser& parser) {
const auto short_descr = parser.get_short_description();
- os << "usage: " << parser.prog_name << ' ' << short_descr << '\n';
+ os << std::format("usage: {} {}\n", parser.prog_name, short_descr);
os << parser.visible;
return os;
}