diff --git a/src/Listen.cxx b/src/Listen.cxx index 8bbe300ee..9ae856048 100644 --- a/src/Listen.cxx +++ b/src/Listen.cxx @@ -27,6 +27,7 @@ #include "config/Net.hxx" #include "lib/fmt/ExceptionFormatter.hxx" #include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "net/AllocatedSocketAddress.hxx" #include "net/UniqueSocketDescriptor.hxx" #include "net/SocketUtil.hxx" @@ -35,7 +36,6 @@ #include "fs/StandardDirectory.hxx" #include "fs/XDG.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include @@ -129,9 +129,9 @@ listen_global_init(const ConfigData &config, ClientListener &listener) ServerSocketAddGeneric(listener, param.value.c_str(), port); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)", - param.value.c_str(), - param.line)); + std::throw_with_nested(FmtRuntimeError("Failed to listen on {} (line {})", + param.value, + param.line)); } } @@ -146,7 +146,8 @@ listen_global_init(const ConfigData &config, ClientListener &listener) try { listener.AddPort(port); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to listen on *:%d: ", port)); + std::throw_with_nested(FmtRuntimeError("Failed to listen on *:{}", + port)); } } diff --git a/src/LogInit.cxx b/src/LogInit.cxx index d98dbfb28..f7e051b2d 100644 --- a/src/LogInit.cxx +++ b/src/LogInit.cxx @@ -22,13 +22,13 @@ #include "LogBackend.hxx" #include "Log.hxx" #include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "config/Param.hxx" #include "config/Data.hxx" #include "config/Option.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "util/StringAPI.hxx" #include "lib/fmt/SystemError.hxx" @@ -79,9 +79,8 @@ log_init_file(int line) out_fd = open_log_file(); if (out_fd < 0) { #ifdef _WIN32 - const std::string out_path_utf8 = out_path.ToUTF8(); - throw FormatRuntimeError("failed to open log file \"%s\" (config line %d)", - out_path_utf8.c_str(), line); + throw FmtRuntimeError("failed to open log file \"{}\" (config line {})", + out_path, line); #else throw FmtErrno("failed to open log file \"{}\" (config line {})", out_path, line); @@ -109,7 +108,7 @@ parse_log_level(const char *value) else if (StringIsEqual(value, "error")) return LogLevel::ERROR; else - throw FormatRuntimeError("unknown log level \"%s\"", value); + throw FmtRuntimeError("unknown log level \"{}\"", value); } #endif diff --git a/src/Main.cxx b/src/Main.cxx index e5c2d8f08..278772ec4 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -59,7 +59,6 @@ #include "config/Domain.hxx" #include "config/Parser.hxx" #include "config/PartitionConfig.hxx" -#include "util/RuntimeError.hxx" #include "util/ScopeExit.hxx" #ifdef ENABLE_DAEMON diff --git a/src/Permission.cxx b/src/Permission.cxx index e693c834c..2309f43f1 100644 --- a/src/Permission.cxx +++ b/src/Permission.cxx @@ -22,11 +22,11 @@ #include "config/Param.hxx" #include "config/Data.hxx" #include "config/Option.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "net/AddressInfo.hxx" #include "net/Resolver.hxx" #include "net/ToString.hxx" #include "util/IterableSplitString.hxx" -#include "util/RuntimeError.hxx" #include "util/StringSplit.hxx" #include @@ -68,8 +68,7 @@ ParsePermission(std::string_view s) if (s == i->name) return i->value; - throw FormatRuntimeError("unknown permission \"%.*s\"", - int(s.size()), s.data()); + throw FmtRuntimeError("unknown permission \"{}\"", s); } static unsigned @@ -103,8 +102,8 @@ initPermissions(const ConfigData &config) const auto [password, permissions] = Split(value, PERMISSION_PASSWORD_CHAR); if (permissions.data() == nullptr) - throw FormatRuntimeError("\"%c\" not found in password string", - PERMISSION_PASSWORD_CHAR); + throw FmtRuntimeError("\"{}\" not found in password string", + PERMISSION_PASSWORD_CHAR); permission_passwords.emplace(password, parsePermissions(permissions)); diff --git a/src/PlaylistDatabase.cxx b/src/PlaylistDatabase.cxx index 7a1515e6b..50461f3db 100644 --- a/src/PlaylistDatabase.cxx +++ b/src/PlaylistDatabase.cxx @@ -19,11 +19,11 @@ #include "PlaylistDatabase.hxx" #include "db/PlaylistVector.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "io/LineReader.hxx" #include "io/BufferedOutputStream.hxx" #include "time/ChronoUtil.hxx" #include "util/StringStrip.hxx" -#include "util/RuntimeError.hxx" #include @@ -55,8 +55,7 @@ playlist_metadata_load(LineReader &file, PlaylistVector &pv, const char *name) std::strcmp(line, "playlist_end") != 0) { colon = std::strchr(line, ':'); if (colon == nullptr || colon == line) - throw FormatRuntimeError("unknown line in db: %s", - line); + throw FmtRuntimeError("unknown line in db: {}", line); *colon++ = 0; value = StripLeft(colon); @@ -64,8 +63,7 @@ playlist_metadata_load(LineReader &file, PlaylistVector &pv, const char *name) if (std::strcmp(line, "mtime") == 0) pm.mtime = std::chrono::system_clock::from_time_t(strtol(value, nullptr, 10)); else - throw FormatRuntimeError("unknown line in db: %s", - line); + throw FmtRuntimeError("unknown line in db: {}", line); } pv.UpdateOrInsert(std::move(pm)); diff --git a/src/SongSave.cxx b/src/SongSave.cxx index f9dfb7e6f..5df013722 100644 --- a/src/SongSave.cxx +++ b/src/SongSave.cxx @@ -23,6 +23,7 @@ #include "song/DetachedSong.hxx" #include "TagSave.hxx" #include "lib/fmt/AudioFormatFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "io/LineReader.hxx" #include "io/BufferedOutputStream.hxx" #include "tag/ParseName.hxx" @@ -32,7 +33,6 @@ #include "util/StringAPI.hxx" #include "util/StringBuffer.hxx" #include "util/StringStrip.hxx" -#include "util/RuntimeError.hxx" #include "util/NumberParser.hxx" #include @@ -97,9 +97,8 @@ song_load(LineReader &file, const char *uri, while ((line = file.ReadLine()) != nullptr && !StringIsEqual(line, SONG_END)) { char *colon = std::strchr(line, ':'); - if (colon == nullptr || colon == line) { - throw FormatRuntimeError("unknown line in db: %s", line); - } + if (colon == nullptr || colon == line) + throw FmtRuntimeError("unknown line in db: {}", line); *colon++ = 0; const char *value = StripLeft(colon); @@ -134,7 +133,7 @@ song_load(LineReader &file, const char *uri, song.SetStartTime(SongTime::FromMS(start_ms)); song.SetEndTime(SongTime::FromMS(end_ms)); } else { - throw FormatRuntimeError("unknown line in db: %s", line); + throw FmtRuntimeError("unknown line in db: {}", line); } } diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx index 84e82ae81..47197624b 100644 --- a/src/archive/plugins/Iso9660ArchivePlugin.cxx +++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx @@ -27,7 +27,8 @@ #include "../ArchiveVisitor.hxx" #include "input/InputStream.hxx" #include "fs/Path.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringCompare.hxx" #include "util/UTF8.hxx" @@ -46,8 +47,8 @@ struct Iso9660 { explicit Iso9660(Path path) :iso(iso9660_open(path.c_str())) { if (iso == nullptr) - throw FormatRuntimeError("Failed to open ISO9660 file %s", - path.c_str()); + throw FmtRuntimeError("Failed to open ISO9660 file {}", + path); } ~Iso9660() noexcept { @@ -238,8 +239,8 @@ Iso9660ArchiveFile::OpenStream(const char *pathname, { auto statbuf = iso9660_ifs_stat_translate(iso->iso, pathname); if (statbuf == nullptr) - throw FormatRuntimeError("not found in the ISO file: %s", - pathname); + throw FmtRuntimeError("not found in the ISO file: {}", + pathname); const lsn_t lsn = statbuf->lsn; const offset_type size = statbuf->size; diff --git a/src/archive/plugins/ZzipArchivePlugin.cxx b/src/archive/plugins/ZzipArchivePlugin.cxx index 258242a34..871e39edf 100644 --- a/src/archive/plugins/ZzipArchivePlugin.cxx +++ b/src/archive/plugins/ZzipArchivePlugin.cxx @@ -26,25 +26,24 @@ #include "../ArchiveFile.hxx" #include "../ArchiveVisitor.hxx" #include "input/InputStream.hxx" +#include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "fs/Path.hxx" #include "lib/fmt/SystemError.hxx" -#include "util/RuntimeError.hxx" #include "util/UTF8.hxx" #include #include -#include /* for PRIoffset (PRIu64) */ - struct ZzipDir { ZZIP_DIR *const dir; explicit ZzipDir(Path path) :dir(zzip_dir_open(path.c_str(), nullptr)) { if (dir == nullptr) - throw FormatRuntimeError("Failed to open ZIP file %s", - path.c_str()); + throw FmtRuntimeError("Failed to open ZIP file {}", + path); } ~ZzipDir() noexcept { @@ -140,9 +139,9 @@ ZzipArchiveFile::OpenStream(const char *pathname, pathname); default: - throw FormatRuntimeError("Failed to open '%s' in ZIP file: %s", - pathname, - zzip_strerror(error)); + throw FmtRuntimeError("Failed to open '{}' in ZIP file: {}", + pathname, + zzip_strerror(error)); } } @@ -161,9 +160,8 @@ ZzipInputStream::Read(std::unique_lock &, void *ptr, size_t read_size) throw std::runtime_error("zzip_file_read() has failed"); if (nbytes == 0 && !IsEOF()) - throw FormatRuntimeError("Unexpected end of file %s" - " at %" PRIoffset " of %" PRIoffset, - GetURI(), GetOffset(), GetSize()); + throw FmtRuntimeError("Unexpected end of file {} at {} of {}", + GetURI(), GetOffset(), GetSize()); offset = zzip_tell(file); return nbytes; diff --git a/src/cmdline/OptionParser.cxx b/src/cmdline/OptionParser.cxx index 8c5997fd3..656c59d1f 100644 --- a/src/cmdline/OptionParser.cxx +++ b/src/cmdline/OptionParser.cxx @@ -19,7 +19,7 @@ #include "OptionParser.hxx" #include "OptionDef.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringCompare.hxx" static const char * @@ -37,7 +37,7 @@ OptionParser::CheckShiftValue(const char *s, const OptionDef &option) return nullptr; if (args.empty()) - throw FormatRuntimeError("Value expected after %s", s); + throw FmtRuntimeError("Value expected after {}", s); return Shift(args); } @@ -78,7 +78,7 @@ OptionParser::IdentifyOption(const char *s) } } - throw FormatRuntimeError("Unknown option: %s", s); + throw FmtRuntimeError("Unknown option: {}", s); } OptionParser::Result diff --git a/src/cmdline/meson.build b/src/cmdline/meson.build index 1a160a1a2..653c41387 100644 --- a/src/cmdline/meson.build +++ b/src/cmdline/meson.build @@ -2,6 +2,9 @@ cmdline = static_library( 'cmdline', 'OptionParser.cxx', include_directories: inc, + dependencies: [ + fmt_dep, + ], ) cmdline_dep = declare_dependency( diff --git a/src/config/Block.cxx b/src/config/Block.cxx index af32337d8..e75d3a51f 100644 --- a/src/config/Block.cxx +++ b/src/config/Block.cxx @@ -21,15 +21,15 @@ #include "Parser.hxx" #include "Path.hxx" #include "fs/AllocatedPath.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include void BlockParam::ThrowWithNested() const { - std::throw_with_nested(FormatRuntimeError("Error in setting \"%s\" on line %i", - name.c_str(), line)); + std::throw_with_nested(FmtRuntimeError("Error in setting \"{}\" on line {}", + name, line)); } int @@ -39,7 +39,7 @@ BlockParam::GetIntValue() const char *endptr; long value2 = strtol(s, &endptr, 0); if (endptr == s || *endptr != 0) - throw FormatRuntimeError("Not a valid number in line %i", line); + throw FmtRuntimeError("Not a valid number in line {}", line); return value2; } @@ -147,6 +147,6 @@ ConfigBlock::GetBlockValue(const char *name, bool default_value) const void ConfigBlock::ThrowWithNested() const { - std::throw_with_nested(FormatRuntimeError("Error in block on line %i", - line)); + std::throw_with_nested(FmtRuntimeError("Error in block on line {}", + line)); } diff --git a/src/config/Data.cxx b/src/config/Data.cxx index 4091a43fc..2aa26c6ec 100644 --- a/src/config/Data.cxx +++ b/src/config/Data.cxx @@ -20,7 +20,7 @@ #include "Data.hxx" #include "Parser.hxx" #include "fs/AllocatedPath.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringAPI.hxx" #include @@ -157,8 +157,8 @@ ConfigData::FindBlock(ConfigBlockOption option, for (const auto &block : GetBlockList(option)) { const char *value2 = block.GetBlockValue(key); if (value2 == nullptr) - throw FormatRuntimeError("block without '%s' in line %d", - key, block.line); + throw FmtRuntimeError("block without '{}' in line {}", + key, block.line); if (StringIsEqual(value2, value)) return █ diff --git a/src/config/File.cxx b/src/config/File.cxx index a72472723..4652a3626 100644 --- a/src/config/File.cxx +++ b/src/config/File.cxx @@ -23,12 +23,12 @@ #include "Block.hxx" #include "Templates.hxx" #include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "system/Error.hxx" #include "util/Tokenizer.hxx" #include "util/StringStrip.hxx" #include "util/StringAPI.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "fs/FileSystem.hxx" #include "fs/List.hxx" #include "fs/Path.hxx" @@ -70,8 +70,8 @@ config_read_name_value(ConfigBlock &block, char *input, unsigned line) const BlockParam *bp = block.GetBlockParam(name); if (bp != nullptr) - throw FormatRuntimeError("\"%s\" is duplicate, first defined on line %i", - name, bp->line); + throw FmtRuntimeError("\"{}\" is duplicate, first defined on line {}", + name, bp->line); block.AddBlockParam(name, value, line); } @@ -123,10 +123,10 @@ ReadConfigBlock(ConfigData &config_data, BufferedReader &reader, if (!option.repeatable) if (const auto *block = config_data.GetBlock(o)) - throw FormatRuntimeError("config parameter \"%s\" is first defined " - "on line %d and redefined on line %u\n", - name, block->line, - reader.GetLineNumber()); + throw FmtRuntimeError("config parameter \"{}\" is first defined " + "on line {} and redefined on line {}", + name, block->line, + reader.GetLineNumber()); /* now parse the block or the value */ @@ -227,8 +227,8 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Path directory) ReadConfigBlock(config_data, reader, name, bo, tokenizer); } else { - throw FormatRuntimeError("unrecognized parameter: %s\n", - name); + throw FmtRuntimeError("unrecognized parameter: {}", + name); } } } @@ -247,9 +247,8 @@ ReadConfigFile(ConfigData &config_data, Path path) try { ReadConfigFile(config_data, reader, path.GetDirectoryName()); } catch (...) { - const std::string path_utf8 = path.ToUTF8(); - std::throw_with_nested(FormatRuntimeError("Error in %s line %u", - path_utf8.c_str(), - reader.GetLineNumber())); + std::throw_with_nested(FmtRuntimeError("Error in {} line {}", + path, + reader.GetLineNumber())); } } diff --git a/src/config/Param.cxx b/src/config/Param.cxx index 91ca2caa4..8f4fd10f1 100644 --- a/src/config/Param.cxx +++ b/src/config/Param.cxx @@ -20,14 +20,14 @@ #include "Param.hxx" #include "Path.hxx" #include "fs/AllocatedPath.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include void ConfigParam::ThrowWithNested() const { - std::throw_with_nested(FormatRuntimeError("Error on line %i", line)); + std::throw_with_nested(FmtRuntimeError("Error on line {}", line)); } AllocatedPath diff --git a/src/config/Parser.cxx b/src/config/Parser.cxx index da437fb7c..fae9c4c93 100644 --- a/src/config/Parser.cxx +++ b/src/config/Parser.cxx @@ -18,7 +18,7 @@ */ #include "Parser.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringStrip.hxx" #include "util/StringUtil.hxx" @@ -36,7 +36,7 @@ ParseBool(const char *value) if (StringArrayContainsCase(f, value)) return false; - throw FormatRuntimeError(R"(Not a valid boolean ("yes" or "no"): "%s")", value); + throw FmtRuntimeError(R"(Not a valid boolean ("yes" or "no"): "{}")", value); } long diff --git a/src/config/Path.cxx b/src/config/Path.cxx index 36f7d7b51..370a0f2f8 100644 --- a/src/config/Path.cxx +++ b/src/config/Path.cxx @@ -22,7 +22,7 @@ #include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/StandardDirectory.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringSplit.hxx" #include @@ -40,7 +40,7 @@ GetHome(const char *user) { AllocatedPath result = GetHomeDir(user); if (result.IsNull()) - throw FormatRuntimeError("no such user: %s", user); + throw FmtRuntimeError("no such user: {}", user); return result; } @@ -107,7 +107,7 @@ ParsePath(const char *path) / AllocatedPath::FromUTF8Throw(rest); } } else if (!PathTraitsUTF8::IsAbsolute(path)) { - throw FormatRuntimeError("not an absolute path: %s", path); + throw FmtRuntimeError("not an absolute path: {}", path); } else { #endif return AllocatedPath::FromUTF8Throw(path); diff --git a/src/config/PlayerConfig.cxx b/src/config/PlayerConfig.cxx index 3980e8556..f2fed568d 100644 --- a/src/config/PlayerConfig.cxx +++ b/src/config/PlayerConfig.cxx @@ -22,7 +22,7 @@ #include "Domain.hxx" #include "Parser.hxx" #include "pcm/AudioParser.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "Log.hxx" #include "MusicChunk.hxx" @@ -38,8 +38,8 @@ GetBufferChunks(const ConfigData &config) buffer_size = param->With([](const char *s){ size_t result = ParseSize(s, KILOBYTE); if (result <= 0) - throw FormatRuntimeError("buffer size \"%s\" is not a " - "positive integer", s); + throw FmtRuntimeError("buffer size \"{}\" is not a " + "positive integer", s); if (result < MIN_BUFFER_SIZE) { FmtWarning(config_domain, "buffer size {} is too small, using {} bytes instead", @@ -53,8 +53,8 @@ GetBufferChunks(const ConfigData &config) unsigned buffer_chunks = buffer_size / CHUNK_SIZE; if (buffer_chunks >= 1 << 15) - throw FormatRuntimeError("buffer size \"%lu\" is too big", - (unsigned long)buffer_size); + throw FmtRuntimeError("buffer size \"{}\" is too big", + buffer_size); return buffer_chunks; } diff --git a/src/config/meson.build b/src/config/meson.build index a07d98663..92d8bd080 100644 --- a/src/config/meson.build +++ b/src/config/meson.build @@ -14,6 +14,7 @@ config = static_library( include_directories: inc, dependencies: [ log_dep, + fmt_dep, ], ) diff --git a/src/db/Configured.cxx b/src/db/Configured.cxx index 8af80bf66..3b77b6457 100644 --- a/src/db/Configured.cxx +++ b/src/db/Configured.cxx @@ -26,7 +26,7 @@ #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "fs/StandardDirectory.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" DatabasePtr CreateConfiguredDatabase(const ConfigData &config, @@ -37,8 +37,8 @@ CreateConfiguredDatabase(const ConfigData &config, const auto *path = config.GetParam(ConfigOption::DB_FILE); if (param != nullptr && path != nullptr) - throw FormatRuntimeError("Found both 'database' (line %d) and 'db_file' (line %d) setting", - param->line, path->line); + throw FmtRuntimeError("Found both 'database' (line {}) and 'db_file' (line }) setting", + param->line, path->line); if (param != nullptr) { param->SetUsed(); diff --git a/src/db/DatabaseGlue.cxx b/src/db/DatabaseGlue.cxx index 449a14a9b..83460ab33 100644 --- a/src/db/DatabaseGlue.cxx +++ b/src/db/DatabaseGlue.cxx @@ -18,11 +18,11 @@ */ #include "DatabaseGlue.hxx" +#include "DatabasePlugin.hxx" #include "Interface.hxx" #include "Registry.hxx" -#include "util/RuntimeError.hxx" #include "config/Block.hxx" -#include "DatabasePlugin.hxx" +#include "lib/fmt/RuntimeError.hxx" DatabasePtr DatabaseGlobalInit(EventLoop &main_event_loop, @@ -35,14 +35,14 @@ DatabaseGlobalInit(EventLoop &main_event_loop, const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name); if (plugin == nullptr) - throw FormatRuntimeError("No such database plugin: %s", - plugin_name); + throw FmtRuntimeError("No such database plugin: {}", + plugin_name); try { return plugin->create(main_event_loop, io_event_loop, listener, block); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to initialize database plugin '%s'", - plugin_name)); + std::throw_with_nested(FmtRuntimeError("Failed to initialize database plugin '{}'", + plugin_name)); } } diff --git a/src/db/plugins/ProxyDatabasePlugin.cxx b/src/db/plugins/ProxyDatabasePlugin.cxx index a42aa4fbb..b0eca0f5d 100644 --- a/src/db/plugins/ProxyDatabasePlugin.cxx +++ b/src/db/plugins/ProxyDatabasePlugin.cxx @@ -37,9 +37,9 @@ #include "tag/Builder.hxx" #include "tag/Tag.hxx" #include "tag/ParseName.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/RecursiveMap.hxx" #include "util/ScopeExit.hxx" -#include "util/RuntimeError.hxx" #include "protocol/Ack.hxx" #include "event/SocketEvent.hxx" #include "event/IdleEvent.hxx" @@ -507,9 +507,9 @@ ProxyDatabase::Connect() if (mpd_connection_cmp_server_version(connection, 0, 20, 0) < 0) { const unsigned *version = mpd_connection_get_server_version(connection); - throw FormatRuntimeError("Connect to MPD %u.%u.%u, but this " - "plugin requires at least version 0.20", - version[0], version[1], version[2]); + throw FmtRuntimeError("Connect to MPD {}.{}.{}, but this " + "plugin requires at least version 0.20", + version[0], version[1], version[2]); } if (!password.empty() && @@ -521,8 +521,8 @@ ProxyDatabase::Connect() std::throw_with_nested(host.empty() ? std::runtime_error("Failed to connect to remote MPD") - : FormatRuntimeError("Failed to connect to remote MPD '%s'", - host.c_str())); + : FmtRuntimeError("Failed to connect to remote MPD '{}'", + host)); } mpd_connection_set_keepalive(connection, keepalive); diff --git a/src/db/plugins/simple/DatabaseSave.cxx b/src/db/plugins/simple/DatabaseSave.cxx index 66860eb54..ae7fec7ea 100644 --- a/src/db/plugins/simple/DatabaseSave.cxx +++ b/src/db/plugins/simple/DatabaseSave.cxx @@ -20,13 +20,13 @@ #include "DatabaseSave.hxx" #include "db/DatabaseLock.hxx" #include "DirectorySave.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "io/BufferedOutputStream.hxx" #include "io/LineReader.hxx" #include "tag/ParseName.hxx" #include "tag/Settings.hxx" #include "fs/Charset.hxx" #include "util/StringCompare.hxx" -#include "util/RuntimeError.hxx" #include "Version.h" #include @@ -102,21 +102,21 @@ db_load_internal(LineReader &file, Directory &music_root) const char *const old_charset = GetFSCharset(); if (*old_charset != 0 && strcmp(new_charset, old_charset) != 0) - throw FormatRuntimeError("Existing database has charset " - "\"%s\" instead of \"%s\"; " - "discarding database file", - new_charset, old_charset); + throw FmtRuntimeError("Existing database has charset " + "\"{}\" instead of \"{}\"; " + "discarding database file", + new_charset, old_charset); } else if ((p = StringAfterPrefix(line, DB_TAG_PREFIX))) { const char *name = p; TagType tag = tag_name_parse(name); if (tag == TAG_NUM_OF_ITEM_TYPES) - throw FormatRuntimeError("Unrecognized tag '%s', " - "discarding database file", - name); + throw FmtRuntimeError("Unrecognized tag '{}', " + "discarding database file", + name); tags[tag] = true; } else { - throw FormatRuntimeError("Malformed line: %s", line); + throw FmtRuntimeError("Malformed line: {}", line); } } diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx index e986f3c87..4957061b4 100644 --- a/src/db/plugins/simple/DirectorySave.cxx +++ b/src/db/plugins/simple/DirectorySave.cxx @@ -26,10 +26,10 @@ #include "io/LineReader.hxx" #include "io/BufferedOutputStream.hxx" #include "time/ChronoUtil.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringAPI.hxx" #include "util/StringCompare.hxx" #include "util/NumberParser.hxx" -#include "util/RuntimeError.hxx" #include @@ -126,8 +126,7 @@ static Directory * directory_load_subdir(LineReader &file, Directory &parent, std::string_view name) { if (parent.FindChild(name) != nullptr) - throw FormatRuntimeError("Duplicate subdirectory '%.*s'", - int(name.size()), name.data()); + throw FmtRuntimeError("Duplicate subdirectory '{}'", name); Directory *directory = parent.CreateChild(name); @@ -141,7 +140,7 @@ directory_load_subdir(LineReader &file, Directory &parent, std::string_view name break; if (!ParseLine(*directory, line)) - throw FormatRuntimeError("Malformed line: %s", line); + throw FmtRuntimeError("Malformed line: {}", line); } directory_load(file, *directory); @@ -167,7 +166,8 @@ directory_load(LineReader &file, Directory &directory) const char *name = p; if (directory.FindSong(name) != nullptr) - throw FormatRuntimeError("Duplicate song '%s'", name); + throw FmtRuntimeError("Duplicate song '{}'", + name); std::string target; auto detached_song = song_load(file, name, @@ -182,7 +182,7 @@ directory_load(LineReader &file, Directory &directory) const char *name = p; playlist_metadata_load(file, directory.playlists, name); } else { - throw FormatRuntimeError("Malformed line: %s", line); + throw FmtRuntimeError("Malformed line: {}", line); } } } diff --git a/src/db/plugins/upnp/ContentDirectoryService.cxx b/src/db/plugins/upnp/ContentDirectoryService.cxx index d8f179d9e..bc9398c48 100644 --- a/src/db/plugins/upnp/ContentDirectoryService.cxx +++ b/src/db/plugins/upnp/ContentDirectoryService.cxx @@ -27,7 +27,6 @@ #include "lib/upnp/Error.hxx" #include "Directory.hxx" #include "util/NumberParser.hxx" -#include "util/RuntimeError.hxx" #include "util/ScopeExit.hxx" #include "util/StringFormat.hxx" diff --git a/src/decoder/DecoderList.cxx b/src/decoder/DecoderList.cxx index 19fd4b3b6..744295106 100644 --- a/src/decoder/DecoderList.cxx +++ b/src/decoder/DecoderList.cxx @@ -23,6 +23,7 @@ #include "Domain.hxx" #include "decoder/Features.h" #include "lib/fmt/ExceptionFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "config/Data.hxx" #include "config/Block.hxx" #include "plugins/AudiofileDecoderPlugin.hxx" @@ -47,7 +48,6 @@ #include "plugins/MpcdecDecoderPlugin.hxx" #include "plugins/FluidsynthDecoderPlugin.hxx" #include "plugins/SidplayDecoderPlugin.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include "PluginUnavailable.hxx" @@ -164,8 +164,8 @@ decoder_plugin_init_all(const ConfigData &config) "Decoder plugin '{}' is unavailable: {}", plugin.name, std::current_exception()); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to initialize decoder plugin '%s'", - plugin.name)); + std::throw_with_nested(FmtRuntimeError("Failed to initialize decoder plugin '{}'", + plugin.name)); } } } diff --git a/src/decoder/Thread.cxx b/src/decoder/Thread.cxx index 0dceedc76..064fec7c2 100644 --- a/src/decoder/Thread.cxx +++ b/src/decoder/Thread.cxx @@ -29,11 +29,11 @@ #include "input/InputStream.hxx" #include "input/Registry.hxx" #include "DecoderList.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "system/Error.hxx" #include "util/MimeType.hxx" #include "util/UriExtract.hxx" #include "util/UriUtil.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/ScopeExit.hxx" #include "util/StringCompare.hxx" @@ -455,8 +455,8 @@ try { if (!allocated.empty()) error_uri = allocated.c_str(); - std::throw_with_nested(FormatRuntimeError("Failed to decode %s", - error_uri)); + std::throw_with_nested(FmtRuntimeError("Failed to decode {}", + error_uri)); } /** @@ -521,7 +521,7 @@ decoder_run_song(DecoderControl &dc, if (!allocated.empty()) error_uri = allocated.c_str(); - throw FormatRuntimeError("Failed to decode %s", error_uri); + throw FmtRuntimeError("Failed to decode {}", error_uri); } dc.client_cond.notify_one(); diff --git a/src/decoder/plugins/FlacPcm.cxx b/src/decoder/plugins/FlacPcm.cxx index d32a19c02..e3c6090e0 100644 --- a/src/decoder/plugins/FlacPcm.cxx +++ b/src/decoder/plugins/FlacPcm.cxx @@ -20,7 +20,7 @@ #include "FlacPcm.hxx" #include "pcm/CheckAudioFormat.hxx" #include "lib/xiph/FlacAudioFormat.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include @@ -30,8 +30,8 @@ FlacPcmImport::Open(unsigned sample_rate, unsigned bits_per_sample, { auto sample_format = FlacSampleFormat(bits_per_sample); if (sample_format == SampleFormat::UNDEFINED) - throw FormatRuntimeError("Unsupported FLAC bit depth: %u", - bits_per_sample); + throw FmtRuntimeError("Unsupported FLAC bit depth: {}", + bits_per_sample); audio_format = CheckAudioFormat(sample_rate, sample_format, channels); } diff --git a/src/decoder/plugins/MikmodDecoderPlugin.cxx b/src/decoder/plugins/MikmodDecoderPlugin.cxx index b3e88c35a..8ee697ff8 100644 --- a/src/decoder/plugins/MikmodDecoderPlugin.cxx +++ b/src/decoder/plugins/MikmodDecoderPlugin.cxx @@ -21,10 +21,10 @@ #include "MikmodDecoderPlugin.hxx" #include "../DecoderAPI.hxx" #include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "tag/Handler.hxx" #include "fs/Path.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include "Version.h" @@ -111,8 +111,8 @@ mikmod_decoder_init(const ConfigBlock &block) mikmod_loop = block.GetBlockValue("loop", false); mikmod_sample_rate = block.GetPositiveValue("sample_rate", 44100U); if (!audio_valid_sample_rate(mikmod_sample_rate)) - throw FormatRuntimeError("Invalid sample rate in line %d: %u", - block.line, mikmod_sample_rate); + throw FmtRuntimeError("Invalid sample rate in line {}: {}", + block.line, mikmod_sample_rate); md_device = 0; md_reverb = 0; diff --git a/src/decoder/plugins/ModplugDecoderPlugin.cxx b/src/decoder/plugins/ModplugDecoderPlugin.cxx index 35490027a..fabfe0702 100644 --- a/src/decoder/plugins/ModplugDecoderPlugin.cxx +++ b/src/decoder/plugins/ModplugDecoderPlugin.cxx @@ -22,8 +22,8 @@ #include "../DecoderAPI.hxx" #include "input/InputStream.hxx" #include "tag/Handler.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #ifdef _WIN32 @@ -56,14 +56,14 @@ modplug_decoder_init(const ConfigBlock &block) } else if (strcmp(modplug_resampling_mode_value, "fir") == 0) { modplug_resampling_mode = MODPLUG_RESAMPLE_FIR; } else { - throw FormatRuntimeError("Invalid resampling mode in line %d: %s", - block.line, modplug_resampling_mode_value); + throw FmtRuntimeError("Invalid resampling mode in line {}: {}", + block.line, modplug_resampling_mode_value); } modplug_loop_count = block.GetBlockValue("loop_count", 0); if (modplug_loop_count < -1) - throw FormatRuntimeError("Invalid loop count in line %d: %i", - block.line, modplug_loop_count); + throw FmtRuntimeError("Invalid loop count in line {}: {}", + block.line, modplug_loop_count); return true; } diff --git a/src/decoder/plugins/OpenmptDecoderPlugin.cxx b/src/decoder/plugins/OpenmptDecoderPlugin.cxx index a7b58c968..0fb6deece 100644 --- a/src/decoder/plugins/OpenmptDecoderPlugin.cxx +++ b/src/decoder/plugins/OpenmptDecoderPlugin.cxx @@ -25,7 +25,6 @@ #include "tag/Handler.hxx" #include "tag/Type.h" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index 62d8a4039..7da908abf 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -24,6 +24,7 @@ #include "OpusTags.hxx" #include "lib/xiph/OggPacket.hxx" #include "lib/xiph/OggFind.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "../DecoderAPI.hxx" #include "decoder/Reader.hxx" #include "input/Reader.hxx" @@ -31,7 +32,6 @@ #include "tag/Handler.hxx" #include "tag/Builder.hxx" #include "input/InputStream.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -206,8 +206,8 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet) assert(IsInitialized() == (output_buffer != nullptr)); if (IsInitialized() && channels != previous_channels) - throw FormatRuntimeError("Next stream has different channels (%u -> %u)", - previous_channels, channels); + throw FmtRuntimeError("Next stream has different channels ({} -> {})", + previous_channels, channels); /* TODO: parse attributes from the OpusHead (sample rate, channels, ...) */ @@ -216,8 +216,8 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet) opus_decoder = opus_decoder_create(opus_sample_rate, channels, &opus_error); if (opus_decoder == nullptr) - throw FormatRuntimeError("libopus error: %s", - opus_strerror(opus_error)); + throw FmtRuntimeError("libopus error: {}", + opus_strerror(opus_error)); if (IsInitialized()) { /* decoder was already initialized by the previous @@ -318,8 +318,8 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet) 0); if (gcc_unlikely(nframes <= 0)) { if (nframes < 0) - throw FormatRuntimeError("libopus error: %s", - opus_strerror(nframes)); + throw FmtRuntimeError("libopus error: {}", + opus_strerror(nframes)); else return; } diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx index bca3acfe0..70d64054f 100644 --- a/src/decoder/plugins/SidplayDecoderPlugin.cxx +++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx @@ -25,17 +25,17 @@ #include "song/DetachedSong.hxx" #include "fs/Path.hxx" #include "fs/AllocatedPath.hxx" +#include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/icu/Converter.hxx" #ifdef HAVE_SIDPLAYFP #include "io/FileReader.hxx" -#include "util/RuntimeError.hxx" #endif #include "util/StringFormat.hxx" #include "util/Domain.hxx" #include "util/AllocatedString.hxx" #include "util/CharUtil.hxx" #include "util/ByteOrder.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #ifdef HAVE_SIDPLAYFP @@ -88,10 +88,7 @@ static void loadRom(const Path rom_path, uint8_t *dump) { FileReader romDump(rom_path); if (romDump.Read(dump, rom_size) != rom_size) - { - throw FormatRuntimeError - ("Could not load rom dump '%s'", rom_path.c_str()); - } + throw FmtRuntimeError("Could not load rom dump '{}'", rom_path); } #endif @@ -108,8 +105,8 @@ sidplay_load_songlength_db(const Path path) bool error = db->open(path.c_str()) < 0; #endif if (error) - throw FormatRuntimeError("unable to read songlengths file %s: %s", - path.c_str(), db->error()); + throw FmtRuntimeError("unable to read songlengths file {}: {}", + path, db->error()); return db; } diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx index 2f3781559..987ce02c4 100644 --- a/src/decoder/plugins/WavpackDecoderPlugin.cxx +++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx @@ -24,10 +24,11 @@ #include "pcm/CheckAudioFormat.hxx" #include "tag/Handler.hxx" #include "fs/Path.hxx" +#include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/AllocatedString.hxx" #include "util/Math.hxx" #include "util/ScopeExit.hxx" -#include "util/RuntimeError.hxx" #include @@ -54,8 +55,8 @@ WavpackOpenInput(Path path, int flags, int norm_offset) auto *wpc = WavpackOpenFileInput(path.c_str(), error, flags, norm_offset); if (wpc == nullptr) - throw FormatRuntimeError("failed to open WavPack file \"%s\": %s", - path.c_str(), error); + throw FmtRuntimeError("failed to open WavPack file \"{}\": {}", + path, error); return wpc; } @@ -72,8 +73,8 @@ WavpackOpenInput(const WavpackStreamReader64 &reader, void *wv_id, void *wvc_id, wv_id, wvc_id, error, flags, norm_offset); if (wpc == nullptr) - throw FormatRuntimeError("failed to open WavPack stream: %s", - error); + throw FmtRuntimeError("failed to open WavPack stream: {}", + error); return wpc; } diff --git a/src/encoder/Configured.cxx b/src/encoder/Configured.cxx index 9a5890327..4ecce1ff7 100644 --- a/src/encoder/Configured.cxx +++ b/src/encoder/Configured.cxx @@ -21,8 +21,8 @@ #include "EncoderList.hxx" #include "EncoderPlugin.hxx" #include "config/Block.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringAPI.hxx" -#include "util/RuntimeError.hxx" static const EncoderPlugin & GetConfiguredEncoderPlugin(const ConfigBlock &block, bool shout_legacy) @@ -43,7 +43,7 @@ GetConfiguredEncoderPlugin(const ConfigBlock &block, bool shout_legacy) const auto plugin = encoder_plugin_get(name); if (plugin == nullptr) - throw FormatRuntimeError("No such encoder: %s", name); + throw FmtRuntimeError("No such encoder: {}", name); return *plugin; } diff --git a/src/encoder/meson.build b/src/encoder/meson.build index 9b21eeca4..2b8ed9f9c 100644 --- a/src/encoder/meson.build +++ b/src/encoder/meson.build @@ -35,6 +35,9 @@ encoder_glue = static_library( 'ToOutputStream.cxx', 'EncoderList.cxx', include_directories: inc, + dependencies: [ + fmt_dep, + ], ) encoder_glue_dep = declare_dependency( diff --git a/src/encoder/plugins/FlacEncoderPlugin.cxx b/src/encoder/plugins/FlacEncoderPlugin.cxx index 83768bf6c..7e75877c5 100644 --- a/src/encoder/plugins/FlacEncoderPlugin.cxx +++ b/src/encoder/plugins/FlacEncoderPlugin.cxx @@ -21,8 +21,8 @@ #include "../EncoderAPI.hxx" #include "pcm/AudioFormat.hxx" #include "pcm/Buffer.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/DynamicFifoBuffer.hxx" -#include "util/RuntimeError.hxx" #include "util/Serial.hxx" #include "util/SpanCast.hxx" #include "util/StringUtil.hxx" @@ -147,25 +147,25 @@ flac_encoder_setup(FLAC__StreamEncoder *fse, unsigned compression, bool oggflac, } if (!FLAC__stream_encoder_set_compression_level(fse, compression)) - throw FormatRuntimeError("error setting flac compression to %d", - compression); + throw FmtRuntimeError("error setting flac compression to {}", + compression); if (!FLAC__stream_encoder_set_channels(fse, audio_format.channels)) - throw FormatRuntimeError("error setting flac channels num to %d", - audio_format.channels); + throw FmtRuntimeError("error setting flac channels num to {}", + audio_format.channels); if (!FLAC__stream_encoder_set_bits_per_sample(fse, bits_per_sample)) - throw FormatRuntimeError("error setting flac bit format to %d", - bits_per_sample); + throw FmtRuntimeError("error setting flac bit format to {}", + bits_per_sample); if (!FLAC__stream_encoder_set_sample_rate(fse, audio_format.sample_rate)) - throw FormatRuntimeError("error setting flac sample rate to %d", - audio_format.sample_rate); + throw FmtRuntimeError("error setting flac sample rate to {}", + audio_format.sample_rate); if (oggflac && !FLAC__stream_encoder_set_ogg_serial_number(fse, GenerateSerial())) - throw FormatRuntimeError("error setting ogg serial number"); + throw std::runtime_error{"error setting ogg serial number"}; } FlacEncoder::FlacEncoder(AudioFormat _audio_format, FLAC__StreamEncoder *_fse, unsigned _compression, bool _oggflac, bool _oggchaining) @@ -188,8 +188,8 @@ FlacEncoder::FlacEncoder(AudioFormat _audio_format, FLAC__StreamEncoder *_fse, u this); if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) - throw FormatRuntimeError("failed to initialize encoder: %s\n", - FLAC__StreamEncoderInitStatusString[init_status]); + throw FmtRuntimeError("failed to initialize encoder: {}", + FLAC__StreamEncoderInitStatusString[init_status]); } Encoder * @@ -250,8 +250,8 @@ FlacEncoder::SendTag(const Tag &tag) FLAC__metadata_object_delete(metadata); if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) - throw FormatRuntimeError("failed to initialize encoder: %s\n", - FLAC__StreamEncoderInitStatusString[init_status]); + throw FmtRuntimeError("failed to initialize encoder: {}", + FLAC__StreamEncoderInitStatusString[init_status]); } template diff --git a/src/encoder/plugins/LameEncoderPlugin.cxx b/src/encoder/plugins/LameEncoderPlugin.cxx index 56bbd9f75..dc43dc2f6 100644 --- a/src/encoder/plugins/LameEncoderPlugin.cxx +++ b/src/encoder/plugins/LameEncoderPlugin.cxx @@ -20,9 +20,9 @@ #include "LameEncoderPlugin.hxx" #include "../EncoderAPI.hxx" #include "pcm/AudioFormat.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/NumberParser.hxx" #include "util/ReusableArray.hxx" -#include "util/RuntimeError.hxx" #include "util/SpanCast.hxx" #include @@ -79,9 +79,9 @@ PreparedLameEncoder::PreparedLameEncoder(const ConfigBlock &block) quality = float(ParseDouble(value, &endptr)); if (*endptr != '\0' || quality < -1.0f || quality > 10.0f) - throw FormatRuntimeError("quality \"%s\" is not a number in the " - "range -1 to 10", - value); + throw FmtRuntimeError("quality \"{}\" is not a number in the " + "range -1 to 10", + value); if (block.GetBlockValue("bitrate") != nullptr) throw std::runtime_error("quality and bitrate are both defined"); diff --git a/src/encoder/plugins/ShineEncoderPlugin.cxx b/src/encoder/plugins/ShineEncoderPlugin.cxx index 4e0edfe6a..56b29288e 100644 --- a/src/encoder/plugins/ShineEncoderPlugin.cxx +++ b/src/encoder/plugins/ShineEncoderPlugin.cxx @@ -20,8 +20,8 @@ #include "ShineEncoderPlugin.hxx" #include "../EncoderAPI.hxx" #include "pcm/AudioFormat.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/DynamicFifoBuffer.hxx" -#include "util/RuntimeError.hxx" #include "util/SpanCast.hxx" extern "C" @@ -121,11 +121,11 @@ SetupShine(shine_config_t config, AudioFormat &audio_format) audio_format.channels == 2 ? PCM_STEREO : PCM_MONO; if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) - throw FormatRuntimeError("error configuring shine. " - "samplerate %d and bitrate %d configuration" - " not supported.", - config.wave.samplerate, - config.mpeg.bitr); + throw FmtRuntimeError("error configuring shine. " + "samplerate {} and bitrate {} configuration" + " not supported.", + config.wave.samplerate, + config.mpeg.bitr); auto shine = shine_initialise(&config); if (!shine) diff --git a/src/encoder/plugins/TwolameEncoderPlugin.cxx b/src/encoder/plugins/TwolameEncoderPlugin.cxx index 00c8466d6..f07d6a33b 100644 --- a/src/encoder/plugins/TwolameEncoderPlugin.cxx +++ b/src/encoder/plugins/TwolameEncoderPlugin.cxx @@ -20,8 +20,8 @@ #include "TwolameEncoderPlugin.hxx" #include "../EncoderAPI.hxx" #include "pcm/AudioFormat.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/NumberParser.hxx" -#include "util/RuntimeError.hxx" #include "util/SpanCast.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -96,9 +96,9 @@ PreparedTwolameEncoder::PreparedTwolameEncoder(const ConfigBlock &block) quality = float(ParseDouble(value, &endptr)); if (*endptr != '\0' || quality < -1.0f || quality > 10.0f) - throw FormatRuntimeError("quality \"%s\" is not a number in the " - "range -1 to 10", - value); + throw FmtRuntimeError("quality \"{}\" is not a number in the " + "range -1 to 10", + value); if (block.GetBlockValue("bitrate") != nullptr) throw std::runtime_error("quality and bitrate are both defined"); diff --git a/src/encoder/plugins/VorbisEncoderPlugin.cxx b/src/encoder/plugins/VorbisEncoderPlugin.cxx index 2c3a4e24c..e7ef60597 100644 --- a/src/encoder/plugins/VorbisEncoderPlugin.cxx +++ b/src/encoder/plugins/VorbisEncoderPlugin.cxx @@ -19,12 +19,12 @@ #include "VorbisEncoderPlugin.hxx" #include "OggEncoder.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/xiph/VorbisComment.hxx" #include "pcm/AudioFormat.hxx" #include "config/Domain.hxx" #include "util/StringUtil.hxx" #include "util/NumberParser.hxx" -#include "util/RuntimeError.hxx" #include @@ -88,9 +88,9 @@ PreparedVorbisEncoder::PreparedVorbisEncoder(const ConfigBlock &block) quality = ParseDouble(value, &endptr); if (*endptr != '\0' || quality < -1.0f || quality > 10.0f) - throw FormatRuntimeError("quality \"%s\" is not a number in the " - "range -1 to 10", - value); + throw FmtRuntimeError("quality \"{}\" is not a number in the " + "range -1 to 10", + value); if (block.GetBlockValue("bitrate") != nullptr) throw std::runtime_error("quality and bitrate are both defined"); diff --git a/src/event/ServerSocket.cxx b/src/event/ServerSocket.cxx index be8e0f9db..493bd2b42 100644 --- a/src/event/ServerSocket.cxx +++ b/src/event/ServerSocket.cxx @@ -19,6 +19,7 @@ #include "ServerSocket.hxx" #include "lib/fmt/ExceptionFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "net/IPv4Address.hxx" #include "net/IPv6Address.hxx" #include "net/StaticSocketAddress.hxx" @@ -31,7 +32,6 @@ #include "net/ToString.hxx" #include "event/SocketEvent.hxx" #include "fs/AllocatedPath.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -255,8 +255,8 @@ ServerSocket::Open() const auto address_string = i.ToString(); try { - std::throw_with_nested(FormatRuntimeError("Failed to bind to '%s'", - address_string.c_str())); + std::throw_with_nested(FmtRuntimeError("Failed to bind to '{}'", + address_string)); } catch (...) { last_error = std::current_exception(); } diff --git a/src/filter/Factory.cxx b/src/filter/Factory.cxx index 33ac0ecf0..9b727122d 100644 --- a/src/filter/Factory.cxx +++ b/src/filter/Factory.cxx @@ -22,7 +22,7 @@ #include "Prepared.hxx" #include "config/Data.hxx" #include "config/Block.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" std::unique_ptr FilterFactory::MakeFilter(const char *name) @@ -30,8 +30,8 @@ FilterFactory::MakeFilter(const char *name) const auto *cfg = config.FindBlock(ConfigBlockOption::AUDIO_FILTER, "name", name); if (cfg == nullptr) - throw FormatRuntimeError("Filter template not found: %s", - name); + throw FmtRuntimeError("Filter template not found: {}", + name); cfg->SetUsed(); diff --git a/src/filter/LoadOne.cxx b/src/filter/LoadOne.cxx index abb45e8ad..bd82bc181 100644 --- a/src/filter/LoadOne.cxx +++ b/src/filter/LoadOne.cxx @@ -22,7 +22,7 @@ #include "Registry.hxx" #include "Prepared.hxx" #include "config/Block.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" std::unique_ptr filter_configured_new(const ConfigBlock &block) @@ -33,8 +33,8 @@ filter_configured_new(const ConfigBlock &block) const auto *plugin = filter_plugin_by_name(plugin_name); if (plugin == nullptr) - throw FormatRuntimeError("No such filter plugin: %s", - plugin_name); + throw FmtRuntimeError("No such filter plugin: {}", + plugin_name); return plugin->init(block); } diff --git a/src/filter/meson.build b/src/filter/meson.build index cd491fcc9..4e1123aae 100644 --- a/src/filter/meson.build +++ b/src/filter/meson.build @@ -17,6 +17,9 @@ filter_glue = static_library( 'LoadOne.cxx', 'LoadChain.cxx', include_directories: inc, + dependencies: [ + fmt_dep, + ], ) filter_glue_dep = declare_dependency( diff --git a/src/filter/plugins/RouteFilterPlugin.cxx b/src/filter/plugins/RouteFilterPlugin.cxx index 9827278d6..70b1426d0 100644 --- a/src/filter/plugins/RouteFilterPlugin.cxx +++ b/src/filter/plugins/RouteFilterPlugin.cxx @@ -47,8 +47,8 @@ #include "pcm/AudioFormat.hxx" #include "pcm/Buffer.hxx" #include "pcm/Silence.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringStrip.hxx" -#include "util/RuntimeError.hxx" #include #include @@ -159,8 +159,8 @@ PreparedRouteFilter::PreparedRouteFilter(const ConfigBlock &block) throw std::runtime_error("Malformed 'routes' specification"); if (source >= MAX_CHANNELS) - throw FormatRuntimeError("Invalid source channel number: %u", - source); + throw FmtRuntimeError("Invalid source channel number: {}", + source); if (source >= min_input_channels) min_input_channels = source + 1; @@ -173,8 +173,8 @@ PreparedRouteFilter::PreparedRouteFilter(const ConfigBlock &block) throw std::runtime_error("Malformed 'routes' specification"); if (dest >= MAX_CHANNELS) - throw FormatRuntimeError("Invalid destination channel number: %u", - dest); + throw FmtRuntimeError("Invalid destination channel number: {}", + dest); if (dest >= min_output_channels) min_output_channels = dest + 1; diff --git a/src/filter/plugins/TwoFilters.cxx b/src/filter/plugins/TwoFilters.cxx index 9a5b1eb16..01503b93c 100644 --- a/src/filter/plugins/TwoFilters.cxx +++ b/src/filter/plugins/TwoFilters.cxx @@ -19,7 +19,8 @@ #include "TwoFilters.hxx" #include "pcm/AudioFormat.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/AudioFormatFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringBuffer.hxx" std::span @@ -50,9 +51,8 @@ PreparedTwoFilters::Open(AudioFormat &audio_format) auto b = second->Open(b_in_format); if (b_in_format != a_out_format) - throw FormatRuntimeError("Audio format not supported by filter '%s': %s", - second_name.c_str(), - ToString(a_out_format).c_str()); + throw FmtRuntimeError("Audio format not supported by filter '{}': {}", + second_name, a_out_format); return std::make_unique(std::move(a), std::move(b)); diff --git a/src/input/Init.cxx b/src/input/Init.cxx index 406cc06b0..f87d87a50 100644 --- a/src/input/Init.cxx +++ b/src/input/Init.cxx @@ -25,8 +25,8 @@ #include "config/Block.hxx" #include "Log.hxx" #include "PluginUnavailable.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include #include @@ -80,8 +80,8 @@ input_stream_global_init(const ConfigData &config, EventLoop &event_loop) plugin->name, e.what()); continue; } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to initialize input plugin '%s'", - plugin->name)); + std::throw_with_nested(FmtRuntimeError("Failed to initialize input plugin '{}'", + plugin->name)); } } } diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx index 110dd842d..7e086692c 100644 --- a/src/input/plugins/CdioParanoiaInputPlugin.cxx +++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx @@ -23,11 +23,11 @@ #include "CdioParanoiaInputPlugin.hxx" #include "lib/cdio/Paranoia.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "../InputStream.hxx" #include "../InputPlugin.hxx" #include "util/TruncateString.hxx" #include "util/StringCompare.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/ByteOrder.hxx" #include "util/ScopeExit.hxx" @@ -114,8 +114,8 @@ input_cdio_init(EventLoop &, const ConfigBlock &block) else if (strcmp(value, "big_endian") == 0) default_reverse_endian = IsLittleEndian(); else - throw FormatRuntimeError("Unrecognized 'default_byte_order' setting: %s", - value); + throw FmtRuntimeError("Unrecognized 'default_byte_order' setting: {}", + value); } speed = block.GetBlockValue("speed",0U); @@ -263,8 +263,8 @@ input_cdio_open(const char *uri, default: cdio_cddap_close_no_free_cdio(drv); cdio_destroy(cdio); - throw FormatRuntimeError("Drive returns unknown data type %d", - be); + throw FmtRuntimeError("Drive returns unknown data type {}", + be); } lsn_t lsn_from, lsn_to; @@ -287,8 +287,8 @@ CdioParanoiaInputStream::Seek(std::unique_lock &, offset_type new_offset) { if (new_offset > size) - throw FormatRuntimeError("Invalid offset to seek %ld (%ld)", - (long int)new_offset, (long int)size); + throw FmtRuntimeError("Invalid offset to seek {} ({})", + new_offset, size); /* simple case */ if (new_offset == offset) diff --git a/src/input/plugins/FileInputPlugin.cxx b/src/input/plugins/FileInputPlugin.cxx index dff0279b1..1f1589cb7 100644 --- a/src/input/plugins/FileInputPlugin.cxx +++ b/src/input/plugins/FileInputPlugin.cxx @@ -21,11 +21,10 @@ #include "../InputStream.hxx" #include "fs/Path.hxx" #include "fs/FileInfo.hxx" +#include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "io/FileReader.hxx" #include "io/FileDescriptor.hxx" -#include "util/RuntimeError.hxx" - -#include // for PRIu64 (PRIoffset) #include #include @@ -63,8 +62,7 @@ OpenFileInputStream(Path path, Mutex &mutex) const FileInfo info = reader.GetFileInfo(); if (!info.IsRegular()) - throw FormatRuntimeError("Not a regular file: %s", - path.c_str()); + throw FmtRuntimeError("Not a regular file: {}", path); #ifdef POSIX_FADV_SEQUENTIAL posix_fadvise(reader.GetFD().Get(), (off_t)0, info.GetSize(), @@ -100,9 +98,9 @@ FileInputStream::Read(std::unique_lock &, } if (nbytes == 0 && !IsEOF()) - throw FormatRuntimeError("Unexpected end of file %s" - " at %" PRIoffset " of %" PRIoffset, - GetURI(), GetOffset(), GetSize()); + throw FmtRuntimeError("Unexpected end of file {}" + " at {} of {}", + GetURI(), GetOffset(), GetSize()); offset += nbytes; return nbytes; diff --git a/src/input/plugins/QobuzErrorParser.cxx b/src/input/plugins/QobuzErrorParser.cxx index 448c11d03..789f17832 100644 --- a/src/input/plugins/QobuzErrorParser.cxx +++ b/src/input/plugins/QobuzErrorParser.cxx @@ -19,8 +19,7 @@ #include "QobuzErrorParser.hxx" #include "lib/yajl/Callbacks.hxx" -#include "util/RuntimeError.hxx" - +#include "lib/fmt/RuntimeError.hxx" using std::string_view_literals::operator""sv; @@ -46,7 +45,7 @@ QobuzErrorParser::QobuzErrorParser(unsigned _status, { auto i = headers.find("content-type"); if (i == headers.end() || i->second.find("/json") == i->second.npos) - throw FormatRuntimeError("Status %u from Qobuz", status); + throw FmtRuntimeError("Status {} from Qobuz", status); } void @@ -55,10 +54,9 @@ QobuzErrorParser::OnEnd() YajlResponseParser::OnEnd(); if (!message.empty()) - throw FormatRuntimeError("Error from Qobuz: %s", - message.c_str()); + throw FmtRuntimeError("Error from Qobuz: {}", message); else - throw FormatRuntimeError("Status %u from Qobuz", status); + throw FmtRuntimeError("Status {} from Qobuz", status); } inline bool diff --git a/src/input/plugins/UringInputPlugin.cxx b/src/input/plugins/UringInputPlugin.cxx index 33574a27b..91aa5b229 100644 --- a/src/input/plugins/UringInputPlugin.cxx +++ b/src/input/plugins/UringInputPlugin.cxx @@ -21,12 +21,12 @@ #include "../AsyncInputStream.hxx" #include "event/Call.hxx" #include "event/Loop.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/fmt/SystemError.hxx" #include "io/Open.hxx" #include "io/UniqueFileDescriptor.hxx" #include "io/uring/ReadOperation.hxx" #include "io/uring/Queue.hxx" -#include "util/RuntimeError.hxx" #include @@ -191,7 +191,7 @@ OpenUringInputStream(const char *path, Mutex &mutex) throw FmtErrno("Failed to access {}", path); if (!S_ISREG(st.st_mode)) - throw FormatRuntimeError("Not a regular file: %s", path); + throw FmtRuntimeError("Not a regular file: {}", path); return std::make_unique(*uring_input_event_loop, *uring_input_queue, diff --git a/src/io/FileReader.cxx b/src/io/FileReader.cxx index 3287e544c..aadb36f19 100644 --- a/src/io/FileReader.cxx +++ b/src/io/FileReader.cxx @@ -62,7 +62,7 @@ FileReader::Read(void *data, std::size_t size) DWORD nbytes; if (!ReadFile(handle, data, size, &nbytes, nullptr)) - throw FmtLastError("Failed to read from %s", path); + throw FmtLastError("Failed to read from {}", path); return nbytes; } diff --git a/src/lib/alsa/HwSetup.cxx b/src/lib/alsa/HwSetup.cxx index 4083947ea..ca653859c 100644 --- a/src/lib/alsa/HwSetup.cxx +++ b/src/lib/alsa/HwSetup.cxx @@ -22,9 +22,9 @@ #include "Format.hxx" #include "lib/fmt/AudioFormatFormatter.hxx" #include "lib/fmt/ToBuffer.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/ByteOrder.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "pcm/AudioFormat.hxx" #include "Log.hxx" #include "config.h" @@ -224,8 +224,8 @@ SetupHw(snd_pcm_t *pcm, requested_sample_rate)); if (output_sample_rate == 0) - throw FormatRuntimeError("Failed to configure sample rate %u Hz", - audio_format.sample_rate); + throw FmtRuntimeError("Failed to configure sample rate {} Hz", + audio_format.sample_rate); if (output_sample_rate != requested_sample_rate) audio_format.sample_rate = params.CalcInputSampleRate(output_sample_rate); diff --git a/src/lib/alsa/NonBlock.cxx b/src/lib/alsa/NonBlock.cxx index 4b6993772..adc78d1a2 100644 --- a/src/lib/alsa/NonBlock.cxx +++ b/src/lib/alsa/NonBlock.cxx @@ -20,7 +20,6 @@ #include "NonBlock.hxx" #include "Error.hxx" #include "event/MultiSocketMonitor.hxx" -#include "util/RuntimeError.hxx" Event::Duration AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm) diff --git a/src/lib/dbus/Error.cxx b/src/lib/dbus/Error.cxx index 4fd6dac22..4a4b48354 100644 --- a/src/lib/dbus/Error.cxx +++ b/src/lib/dbus/Error.cxx @@ -31,12 +31,12 @@ */ #include "Error.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" void ODBus::Error::Throw(const char *prefix) const { - throw FormatRuntimeError("%s: %s", prefix, GetMessage()); + throw FmtRuntimeError("{}: {}", prefix, GetMessage()); } void diff --git a/src/lib/ffmpeg/Error.cxx b/src/lib/ffmpeg/Error.cxx index a1bcf872b..03b3e08f4 100644 --- a/src/lib/ffmpeg/Error.cxx +++ b/src/lib/ffmpeg/Error.cxx @@ -18,7 +18,7 @@ */ #include "Error.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" extern "C" { #include @@ -37,5 +37,5 @@ MakeFfmpegError(int errnum, const char *prefix) { char msg[256]; av_strerror(errnum, msg, sizeof(msg)); - return FormatRuntimeError("%s: %s", prefix, msg); + return FmtRuntimeError("{}: {}", prefix, msg); } diff --git a/src/lib/ffmpeg/Filter.cxx b/src/lib/ffmpeg/Filter.cxx index 012e7142f..ce36bd2ff 100644 --- a/src/lib/ffmpeg/Filter.cxx +++ b/src/lib/ffmpeg/Filter.cxx @@ -21,7 +21,7 @@ #include "ChannelLayout.hxx" #include "SampleFormat.hxx" #include "pcm/AudioFormat.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include @@ -34,7 +34,7 @@ RequireFilterByName(const char *name) { const auto *filter = avfilter_get_by_name(name); if (filter == nullptr) - throw FormatRuntimeError("No such FFmpeg filter: '%s'", name); + throw FmtRuntimeError("No such FFmpeg filter: '{}'", name); return *filter; } diff --git a/src/util/RuntimeError.hxx b/src/lib/fmt/RuntimeError.cxx similarity index 58% rename from src/util/RuntimeError.hxx rename to src/lib/fmt/RuntimeError.cxx index 74cb8a5de..b851d6ecc 100644 --- a/src/util/RuntimeError.hxx +++ b/src/lib/fmt/RuntimeError.cxx @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Max Kellermann + * Copyright 2022 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,40 +27,19 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RUNTIME_ERROR_HXX -#define RUNTIME_ERROR_HXX +#include "RuntimeError.hxx" +#include "ToBuffer.hxx" -#include // IWYU pragma: export -#include - -#include - -#if defined(__clang__) || defined(__GNUC__) -#pragma GCC diagnostic push -// TODO: fix this warning properly -#pragma GCC diagnostic ignored "-Wformat-security" -#endif - -template -static inline std::runtime_error -FormatRuntimeError(const char *fmt, Args&&... args) noexcept +std::runtime_error +VFmtRuntimeError(fmt::string_view format_str, fmt::format_args args) noexcept { - char buffer[1024]; - snprintf(buffer, sizeof(buffer), fmt, std::forward(args)...); - return std::runtime_error(buffer); + const auto msg = VFmtBuffer<512>(format_str, args); + return std::runtime_error{msg}; } -template -inline std::invalid_argument -FormatInvalidArgument(const char *fmt, Args&&... args) noexcept +std::invalid_argument +VFmtInvalidArgument(fmt::string_view format_str, fmt::format_args args) noexcept { - char buffer[1024]; - snprintf(buffer, sizeof(buffer), fmt, std::forward(args)...); - return std::invalid_argument(buffer); + const auto msg = VFmtBuffer<512>(format_str, args); + return std::invalid_argument{msg}; } - -#if defined(__clang__) || defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -#endif diff --git a/src/lib/fmt/RuntimeError.hxx b/src/lib/fmt/RuntimeError.hxx new file mode 100644 index 000000000..af90250d1 --- /dev/null +++ b/src/lib/fmt/RuntimeError.hxx @@ -0,0 +1,75 @@ +/* + * Copyright 2022 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#if FMT_VERSION >= 80000 && FMT_VERSION < 90000 +#include +#endif + +#include // IWYU pragma: export + +[[nodiscard]] [[gnu::pure]] +std::runtime_error +VFmtRuntimeError(fmt::string_view format_str, fmt::format_args args) noexcept; + +template +[[nodiscard]] [[gnu::pure]] +auto +FmtRuntimeError(const S &format_str, Args&&... args) noexcept +{ +#if FMT_VERSION >= 90000 + return VFmtRuntimeError(format_str, + fmt::make_format_args(args...)); +#else + return VFmtRuntimeError(fmt::to_string_view(format_str), + fmt::make_args_checked(format_str, + args...)); +#endif +} + +[[nodiscard]] [[gnu::pure]] +std::invalid_argument +VFmtInvalidArgument(fmt::string_view format_str, fmt::format_args args) noexcept; + +template +[[nodiscard]] [[gnu::pure]] +auto +FmtInvalidArgument(const S &format_str, Args&&... args) noexcept +{ +#if FMT_VERSION >= 90000 + return VFmtInvalidArgument(format_str, + fmt::make_format_args(args...)); +#else + return VFmtInvalidArgument(fmt::to_string_view(format_str), + fmt::make_args_checked(format_str, + args...)); +#endif +} diff --git a/src/lib/fmt/meson.build b/src/lib/fmt/meson.build index 84ddb8a72..793c296fc 100644 --- a/src/lib/fmt/meson.build +++ b/src/lib/fmt/meson.build @@ -10,6 +10,7 @@ endif fmt = static_library( 'fmt', + 'RuntimeError.cxx', 'SystemError.cxx', include_directories: inc, dependencies: libfmt, diff --git a/src/lib/icu/Init.cxx b/src/lib/icu/Init.cxx index 78bec369c..839cf8c4c 100644 --- a/src/lib/icu/Init.cxx +++ b/src/lib/icu/Init.cxx @@ -21,7 +21,6 @@ #include "Collate.hxx" #include "Canonicalize.hxx" #include "Error.hxx" -#include "util/RuntimeError.hxx" #include diff --git a/src/lib/jack/Dynamic.hxx b/src/lib/jack/Dynamic.hxx index b15d7045e..c1332cb8c 100644 --- a/src/lib/jack/Dynamic.hxx +++ b/src/lib/jack/Dynamic.hxx @@ -18,6 +18,7 @@ */ #include "system/Error.hxx" +#include "lib/fmt/RuntimeError.hxx" /* sorry for this horrible piece of code - there's no elegant way to load DLLs at runtime */ @@ -102,7 +103,7 @@ GetFunction(HMODULE h, const char *name, T &result) { auto f = GetProcAddress(h, name); if (f == nullptr) - throw FormatRuntimeError("No such libjack function: %s", name); + throw FmtRuntimeError("No such libjack function: {}", name); result = reinterpret_cast(f); } diff --git a/src/lib/pulse/Error.cxx b/src/lib/pulse/Error.cxx index 94efaa399..c8f3f28f8 100644 --- a/src/lib/pulse/Error.cxx +++ b/src/lib/pulse/Error.cxx @@ -18,7 +18,6 @@ */ #include "Error.hxx" -#include "util/RuntimeError.hxx" #include #include diff --git a/src/lib/yajl/Handle.cxx b/src/lib/yajl/Handle.cxx index d9df886e9..d0eb0aa76 100644 --- a/src/lib/yajl/Handle.cxx +++ b/src/lib/yajl/Handle.cxx @@ -28,7 +28,7 @@ */ #include "Handle.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/ScopeExit.hxx" #include "util/StringStrip.hxx" @@ -60,8 +60,8 @@ Handle::ThrowError() yajl_free_error(handle, str); }; - throw FormatRuntimeError("Failed to parse JSON: %s", - StripErrorMessage((char *)str)); + throw FmtRuntimeError("Failed to parse JSON: {}", + StripErrorMessage((char *)str)); } } // namespace Yajl diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx index 19a69a532..93546995f 100644 --- a/src/mixer/plugins/AlsaMixerPlugin.cxx +++ b/src/mixer/plugins/AlsaMixerPlugin.cxx @@ -20,6 +20,7 @@ #include "AlsaMixerPlugin.hxx" #include "lib/alsa/NonBlock.hxx" #include "lib/alsa/Error.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/fmt/ToBuffer.hxx" #include "mixer/Mixer.hxx" #include "mixer/Listener.hxx" @@ -30,7 +31,6 @@ #include "util/ASCII.hxx" #include "util/Domain.hxx" #include "util/Math.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" extern "C" { @@ -279,7 +279,7 @@ AlsaMixer::Setup() elem = alsa_mixer_lookup_elem(handle, control, index); if (elem == nullptr) - throw FormatRuntimeError("no such mixer control: %s", control); + throw FmtRuntimeError("no such mixer control: {}", control); snd_mixer_elem_set_callback_private(elem, this); snd_mixer_elem_set_callback(elem, ElemCallback); diff --git a/src/mixer/plugins/OssMixerPlugin.cxx b/src/mixer/plugins/OssMixerPlugin.cxx index 7a0edb725..df8a5ee43 100644 --- a/src/mixer/plugins/OssMixerPlugin.cxx +++ b/src/mixer/plugins/OssMixerPlugin.cxx @@ -20,11 +20,11 @@ #include "OssMixerPlugin.hxx" #include "mixer/Mixer.hxx" #include "config/Block.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "io/FileDescriptor.hxx" #include "lib/fmt/SystemError.hxx" #include "util/ASCII.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -91,8 +91,8 @@ OssMixer::Configure(const ConfigBlock &block) if (control != NULL) { volume_control = oss_find_mixer(control); if (volume_control < 0) - throw FormatRuntimeError("no such mixer control: %s", - control); + throw FmtRuntimeError("no such mixer control: {}", + control); } else volume_control = SOUND_MIXER_PCM; } diff --git a/src/mixer/plugins/PulseMixerPlugin.cxx b/src/mixer/plugins/PulseMixerPlugin.cxx index e5713db83..22d717cd7 100644 --- a/src/mixer/plugins/PulseMixerPlugin.cxx +++ b/src/mixer/plugins/PulseMixerPlugin.cxx @@ -18,13 +18,13 @@ */ #include "PulseMixerPlugin.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/pulse/LogError.hxx" #include "lib/pulse/LockGuard.hxx" #include "mixer/Mixer.hxx" #include "mixer/Listener.hxx" #include "output/plugins/PulseOutputPlugin.hxx" #include "util/NumberParser.hxx" -#include "util/RuntimeError.hxx" #include "config/Block.hxx" #include @@ -177,9 +177,9 @@ parse_volume_scale_factor(const char *value) { float factor = ParseFloat(value, &endptr); if (endptr == value || *endptr != '\0' || factor < 0.5f || factor > 5.0f) - throw FormatRuntimeError("\"%s\" is not a number in the " - "range 0.5 to 5.0", - value); + throw FmtRuntimeError("\"{}\" is not a number in the " + "range 0.5 to 5.0", + value); return factor; } diff --git a/src/neighbor/Glue.cxx b/src/neighbor/Glue.cxx index 4a8f47d2c..7cf93c3b4 100644 --- a/src/neighbor/Glue.cxx +++ b/src/neighbor/Glue.cxx @@ -24,7 +24,7 @@ #include "Info.hxx" #include "config/Data.hxx" #include "config/Block.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include @@ -38,8 +38,8 @@ CreateNeighborExplorer(EventLoop &loop, NeighborListener &listener, { const NeighborPlugin *plugin = GetNeighborPluginByName(plugin_name); if (plugin == nullptr) - throw FormatRuntimeError("No such neighbor plugin: %s", - plugin_name); + throw FmtRuntimeError("No such neighbor plugin: {}", + plugin_name); return plugin->create(loop, listener, block); } @@ -72,8 +72,8 @@ NeighborGlue::Open() for (auto k = explorers.begin(); k != i; ++k) k->explorer->Close(); - std::throw_with_nested(FormatRuntimeError("Failed to open neighblor plugin '%s'", - i->name.c_str())); + std::throw_with_nested(FmtRuntimeError("Failed to open neighblor plugin '{}'", + i->name)); } } } diff --git a/src/net/Resolver.cxx b/src/net/Resolver.cxx index 02fc0c2c7..8ab6b682f 100644 --- a/src/net/Resolver.cxx +++ b/src/net/Resolver.cxx @@ -33,7 +33,7 @@ #include "Resolver.hxx" #include "AddressInfo.hxx" #include "HostParser.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/CharUtil.hxx" #ifdef _WIN32 @@ -54,11 +54,17 @@ Resolve(const char *node, const char *service, { struct addrinfo *ai; int error = getaddrinfo(node, service, hints, &ai); - if (error != 0) - throw FormatRuntimeError("Failed to resolve '%s':'%s': %s", - node == nullptr ? "" : node, - service == nullptr ? "" : service, - gai_strerror(error)); + if (error != 0) { +#ifdef _WIN32 + const char *msg = gai_strerrorA(error); +#else + const char *msg = gai_strerror(error); +#endif + throw FmtRuntimeError("Failed to resolve '{}':'{}': {}", + node == nullptr ? "" : node, + service == nullptr ? "" : service, + msg); + } return AddressInfoList(ai); } @@ -89,7 +95,7 @@ FindAndResolveInterfaceName(char *host, size_t size) const unsigned i = if_nametoindex(interface); if (i == 0) - throw FormatRuntimeError("No such interface: %s", interface); + throw FmtRuntimeError("No such interface: {}", interface); sprintf(interface, "%u", i); } diff --git a/src/net/meson.build b/src/net/meson.build index 2e558cd71..03af2d307 100644 --- a/src/net/meson.build +++ b/src/net/meson.build @@ -49,6 +49,9 @@ net = static_library( 'SocketDescriptor.cxx', 'SocketError.cxx', include_directories: inc, + dependencies: [ + fmt_dep, + ], ) net_dep = declare_dependency( diff --git a/src/output/Filtered.cxx b/src/output/Filtered.cxx index ed5402cea..374df4af5 100644 --- a/src/output/Filtered.cxx +++ b/src/output/Filtered.cxx @@ -22,10 +22,10 @@ #include "Domain.hxx" #include "lib/fmt/AudioFormatFormatter.hxx" #include "lib/fmt/ExceptionFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "mixer/Mixer.hxx" #include "mixer/plugins/SoftwareMixerPlugin.hxx" #include "filter/plugins/ConvertFilterPlugin.hxx" -#include "util/RuntimeError.hxx" #include "util/StringBuffer.hxx" #include "Log.hxx" @@ -59,8 +59,8 @@ FilteredAudioOutput::Enable() try { output->Enable(); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to enable output %s", - GetLogName())); + std::throw_with_nested(FmtRuntimeError("Failed to enable output {}", + GetLogName())); } } @@ -76,8 +76,8 @@ FilteredAudioOutput::ConfigureConvertFilter() try { convert_filter_set(convert_filter.Get(), out_audio_format); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to convert for %s", - GetLogName())); + std::throw_with_nested(FmtRuntimeError("Failed to convert for {}", + GetLogName())); } } @@ -89,8 +89,8 @@ FilteredAudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format) try { output->Open(out_audio_format); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to open %s", - GetLogName())); + std::throw_with_nested(FmtRuntimeError("Failed to open {}", + GetLogName())); } FmtDebug(output_domain, diff --git a/src/output/Init.cxx b/src/output/Init.cxx index 535be4e18..ae803a1d5 100644 --- a/src/output/Init.cxx +++ b/src/output/Init.cxx @@ -23,6 +23,7 @@ #include "OutputAPI.hxx" #include "Defaults.hxx" #include "lib/fmt/ExceptionFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "pcm/AudioParser.hxx" #include "mixer/Type.hxx" #include "mixer/Control.hxx" @@ -36,7 +37,6 @@ #include "filter/plugins/TwoFilters.hxx" #include "filter/plugins/VolumeFilterPlugin.hxx" #include "filter/plugins/NormalizeFilterPlugin.hxx" -#include "util/RuntimeError.hxx" #include "util/StringAPI.hxx" #include "util/StringFormat.hxx" #include "Log.hxx" @@ -282,7 +282,8 @@ audio_output_new(EventLoop &normal_event_loop, EventLoop &rt_event_loop, plugin = AudioOutputPlugin_get(p); if (plugin == nullptr) - throw FormatRuntimeError("No such audio output plugin: %s", p); + throw FmtRuntimeError("No such audio output plugin: {}", + p); } else { LogWarning(output_domain, "No 'audio_output' defined in config file"); diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx index 886a03f91..8864d3da7 100644 --- a/src/output/MultipleOutputs.cxx +++ b/src/output/MultipleOutputs.cxx @@ -27,7 +27,7 @@ #include "config/Block.hxx" #include "config/Data.hxx" #include "config/Option.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/StringAPI.hxx" #include @@ -62,8 +62,8 @@ try { mixer_listener); } catch (...) { if (block.line > 0) - std::throw_with_nested(FormatRuntimeError("Failed to configure output in line %i", - block.line)); + std::throw_with_nested(FmtRuntimeError("Failed to configure output in line {}", + block.line)); else throw; } @@ -99,9 +99,9 @@ MultipleOutputs::Configure(EventLoop &event_loop, EventLoop &rt_event_loop, client, block, defaults, &filter_factory); if (HasName(output->GetName())) - throw FormatRuntimeError("output devices with identical " - "names: %s", - output->GetName().c_str()); + throw FmtRuntimeError("output devices with identical " + "names: {}", + output->GetName()); outputs.emplace_back(std::move(output)); }); diff --git a/src/output/Source.cxx b/src/output/Source.cxx index d5d818fcb..9065eafc3 100644 --- a/src/output/Source.cxx +++ b/src/output/Source.cxx @@ -23,8 +23,9 @@ #include "filter/Prepared.hxx" #include "filter/plugins/ReplayGainFilterPlugin.hxx" #include "pcm/Mix.hxx" +#include "lib/fmt/AudioFormatFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "thread/Mutex.hxx" -#include "util/RuntimeError.hxx" #include @@ -198,8 +199,8 @@ AudioOutputSource::FilterChunk(const MusicChunk &chunk) if (!pcm_mix(cross_fade_dither, dest, data.data(), data.size(), in_audio_format.format, mix_ratio)) - throw FormatRuntimeError("Cannot cross-fade format %s", - sample_format_to_string(in_audio_format.format)); + throw FmtRuntimeError("Cannot cross-fade format {}", + in_audio_format.format); data = {(const std::byte *)dest, other_data.size()}; } diff --git a/src/output/Thread.cxx b/src/output/Thread.cxx index 5af7c2c41..ce05cb0ce 100644 --- a/src/output/Thread.cxx +++ b/src/output/Thread.cxx @@ -24,12 +24,12 @@ #include "Domain.hxx" #include "lib/fmt/AudioFormatFormatter.hxx" #include "lib/fmt/ExceptionFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "thread/Util.hxx" #include "thread/Slack.hxx" #include "thread/Name.hxx" #include "util/StringBuffer.hxx" #include "util/ScopeExit.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -145,8 +145,8 @@ AudioOutputControl::InternalOpen(const AudioFormat in_audio_format, output->prepared_other_replay_gain_filter.get(), *output->prepared_filter); } catch (...) { - std::throw_with_nested(FormatRuntimeError("Failed to open filter for %s", - GetLogName())); + std::throw_with_nested(FmtRuntimeError("Failed to open filter for {}", + GetLogName())); } try { diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 69b52b2f3..1cdc39772 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -25,6 +25,7 @@ #include "lib/alsa/NonBlock.hxx" #include "lib/alsa/PeriodBuffer.hxx" #include "lib/alsa/Version.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/fmt/ToBuffer.hxx" #include "../OutputAPI.hxx" #include "../Error.hxx" @@ -34,7 +35,6 @@ #include "thread/Mutex.hxx" #include "thread/Cond.hxx" #include "util/Manual.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "event/MultiSocketMonitor.hxx" #include "event/InjectEvent.hxx" @@ -846,8 +846,8 @@ AlsaOutput::Open(AudioFormat &audio_format) ); } catch (...) { snd_pcm_close(pcm); - std::throw_with_nested(FormatRuntimeError("Error opening ALSA device \"%s\"", - GetDevice())); + std::throw_with_nested(FmtRuntimeError("Error opening ALSA device \"{}\"", + GetDevice())); } work_around_drain_bug = MaybeDmix(pcm) && diff --git a/src/output/plugins/AoOutputPlugin.cxx b/src/output/plugins/AoOutputPlugin.cxx index 8db12c5c4..32fca8e56 100644 --- a/src/output/plugins/AoOutputPlugin.cxx +++ b/src/output/plugins/AoOutputPlugin.cxx @@ -19,10 +19,10 @@ #include "AoOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "thread/SafeSingleton.hxx" #include "system/Error.hxx" #include "util/IterableSplitString.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/StringAPI.hxx" #include "util/StringSplit.hxx" @@ -121,8 +121,8 @@ AoOutput::AoOutput(const ConfigBlock &block) driver = ao_driver_id(value); if (driver < 0) - throw FormatRuntimeError("\"%s\" is not a valid ao driver", - value); + throw FmtRuntimeError("\"{}\" is not a valid ao driver", + value); ao_info *ai = ao_driver_info(driver); if (ai == nullptr) @@ -136,8 +136,8 @@ AoOutput::AoOutput(const ConfigBlock &block) for (const std::string_view i : IterableSplitString(value, ';')) { const auto [n, v] = Split(Strip(i), '='); if (n.empty() || v.data() == nullptr) - throw FormatRuntimeError("problems parsing option \"%.*s\"", - int(i.size()), i.data()); + throw FmtRuntimeError("problems parsing option \"{}\"", + i); ao_append_option(&options, std::string{n}.c_str(), std::string{v}.c_str()); diff --git a/src/output/plugins/FifoOutputPlugin.cxx b/src/output/plugins/FifoOutputPlugin.cxx index 0334e05f0..7b58e6474 100644 --- a/src/output/plugins/FifoOutputPlugin.cxx +++ b/src/output/plugins/FifoOutputPlugin.cxx @@ -21,12 +21,12 @@ #include "../OutputAPI.hxx" #include "../Timer.hxx" #include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "fs/FileInfo.hxx" #include "lib/fmt/SystemError.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include "open.h" @@ -37,7 +37,6 @@ class FifoOutput final : AudioOutput { const AllocatedPath path; - std::string path_utf8; int input = -1; int output = -1; @@ -84,8 +83,6 @@ FifoOutput::FifoOutput(const ConfigBlock &block) if (path.IsNull()) throw std::runtime_error("No \"path\" parameter specified"); - path_utf8 = path.ToUTF8(); - OpenFifo(); } @@ -147,8 +144,8 @@ FifoOutput::Check() } if (!S_ISFIFO(st.st_mode)) - throw FormatRuntimeError("\"%s\" already exists, but is not a FIFO", - path_utf8.c_str()); + throw FmtRuntimeError("\"{}\" already exists, but is not a FIFO", + path); } inline void diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx index 3667e5729..7931d491e 100644 --- a/src/output/plugins/JackOutputPlugin.cxx +++ b/src/output/plugins/JackOutputPlugin.cxx @@ -22,10 +22,10 @@ #include "../OutputAPI.hxx" #include "../Error.hxx" #include "output/Features.h" +#include "lib/fmt/RuntimeError.hxx" #include "thread/Mutex.hxx" #include "util/ScopeExit.hxx" #include "util/IterableSplitString.hxx" -#include "util/RuntimeError.hxx" #include "util/SpanCast.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -123,8 +123,8 @@ private: void Shutdown(const char *reason) noexcept { const std::scoped_lock lock(mutex); - error = std::make_exception_ptr(FormatRuntimeError("JACK connection shutdown: %s", - reason)); + error = std::make_exception_ptr(FmtRuntimeError("JACK connection shutdown: {}", + reason)); } static void OnShutdown(jack_status_t, const char *reason, @@ -416,8 +416,8 @@ JackOutput::Connect() jack_status_t status; client = jack_client_open(name, options, &status, server_name); if (client == nullptr) - throw FormatRuntimeError("Failed to connect to JACK server, status=%d", - status); + throw FmtRuntimeError("Failed to connect to JACK server, status={}", + (unsigned)status); jack_set_process_callback(client, Process, this); jack_on_info_shutdown(client, OnShutdown, this); @@ -430,8 +430,8 @@ JackOutput::Connect() portflags, 0); if (ports[i] == nullptr) { Disconnect(); - throw FormatRuntimeError("Cannot register output port \"%s\"", - source_ports[i].c_str()); + throw FmtRuntimeError("Cannot register output port \"{}\"", + source_ports[i]); } } } @@ -590,8 +590,8 @@ JackOutput::Start() dports[i]); if (ret != 0) { Stop(); - throw FormatRuntimeError("Not a valid JACK port: %s", - dports[i]); + throw FmtRuntimeError("Not a valid JACK port: {}", + dports[i]); } } @@ -604,8 +604,8 @@ JackOutput::Start() duplicate_port); if (ret != 0) { Stop(); - throw FormatRuntimeError("Not a valid JACK port: %s", - duplicate_port); + throw FmtRuntimeError("Not a valid JACK port: {}", + duplicate_port); } } } diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx index 1a86ea02b..17f3dd04c 100644 --- a/src/output/plugins/OSXOutputPlugin.cxx +++ b/src/output/plugins/OSXOutputPlugin.cxx @@ -25,7 +25,7 @@ #include "apple/Throw.hxx" #include "../OutputAPI.hxx" #include "mixer/plugins/OSXMixerPlugin.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/Manual.hxx" #include "pcm/Export.hxx" @@ -247,8 +247,8 @@ osx_output_parse_channel_map(const char *device_name, while (*channel_map_str) { if (inserted_channels >= num_channels) - throw FormatRuntimeError("%s: channel map contains more than %u entries or trailing garbage", - device_name, num_channels); + throw FmtRuntimeError("{}: channel map contains more than {} entries or trailing garbage", + device_name, num_channels); if (!want_number && *channel_map_str == ',') { ++channel_map_str; @@ -262,8 +262,8 @@ osx_output_parse_channel_map(const char *device_name, char *endptr; channel_map[inserted_channels] = strtol(channel_map_str, &endptr, 10); if (channel_map[inserted_channels] < -1) - throw FormatRuntimeError("%s: channel map value %d not allowed (must be -1 or greater)", - device_name, channel_map[inserted_channels]); + throw FmtRuntimeError("{}: channel map value {} not allowed (must be -1 or greater)", + device_name, channel_map[inserted_channels]); channel_map_str = endptr; want_number = false; @@ -275,13 +275,13 @@ osx_output_parse_channel_map(const char *device_name, continue; } - throw FormatRuntimeError("%s: invalid character '%c' in channel map", - device_name, *channel_map_str); + throw FmtRuntimeError("{}: invalid character '{}' in channel map", + device_name, *channel_map_str); } if (inserted_channels < num_channels) - throw FormatRuntimeError("%s: channel map contains less than %u entries", - device_name, num_channels); + throw FmtRuntimeError("{}: channel map contains less than {} entries", + device_name, num_channels); } static UInt32 @@ -453,8 +453,8 @@ osx_output_set_device_format(AudioDeviceID dev_id, sizeof(output_format), &output_format); if (err != noErr) - throw FormatRuntimeError("Failed to change the stream format: %d", - err); + throw FmtRuntimeError("Failed to change the stream format: {}", + err); } return output_format.mSampleRate; @@ -582,8 +582,7 @@ FindAudioDeviceByName(const char *name) return id; } - throw FormatRuntimeError("Found no audio device with name '%s' ", - name); + throw FmtRuntimeError("Found no audio device names '{}'", name); } static void diff --git a/src/output/plugins/OpenALOutputPlugin.cxx b/src/output/plugins/OpenALOutputPlugin.cxx index 0fbbc28c0..432d9bf22 100644 --- a/src/output/plugins/OpenALOutputPlugin.cxx +++ b/src/output/plugins/OpenALOutputPlugin.cxx @@ -19,7 +19,7 @@ #include "OpenALOutputPlugin.hxx" #include "../OutputAPI.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include @@ -126,14 +126,14 @@ OpenALOutput::SetupContext() { device = alcOpenDevice(device_name); if (device == nullptr) - throw FormatRuntimeError("Error opening OpenAL device \"%s\"", - device_name); + throw FmtRuntimeError("Error opening OpenAL device \"{}\"", + device_name); context = alcCreateContext(device, nullptr); if (context == nullptr) { alcCloseDevice(device); - throw FormatRuntimeError("Error creating context for \"%s\"", - device_name); + throw FmtRuntimeError("Error creating context for \"{}\"", + device_name); } } diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx index d49558b48..3346aa3af 100644 --- a/src/output/plugins/ShoutOutputPlugin.cxx +++ b/src/output/plugins/ShoutOutputPlugin.cxx @@ -21,7 +21,7 @@ #include "../OutputAPI.hxx" #include "encoder/EncoderInterface.hxx" #include "encoder/Configured.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/ScopeExit.hxx" #include "util/StringAPI.hxx" @@ -105,8 +105,8 @@ require_block_string(const ConfigBlock &block, const char *name) { const char *value = block.GetBlockValue(name); if (value == nullptr) - throw FormatRuntimeError("no \"%s\" defined for shout device defined " - "at line %d\n", name, block.line); + throw FmtRuntimeError("no \"{}\" defined for shout device defined " + "at line {}\n", name, block.line); return value; } @@ -140,8 +140,8 @@ ParseShoutTls(const char *value) else if (StringIsEqual(value, "rfc2817")) return SHOUT_TLS_RFC2817; else - throw FormatRuntimeError("invalid shout TLS option \"%s\"", - value); + throw FmtRuntimeError("invalid shout TLS option \"{}\"", + value); } #endif @@ -163,17 +163,17 @@ ParseShoutProtocol(const char *value, const char *mime_type) if (StringIsEqual(value, "shoutcast")) { if (!StringIsEqual(mime_type, "audio/mpeg")) - throw FormatRuntimeError("you cannot stream \"%s\" to shoutcast, use mp3", - mime_type); + throw FmtRuntimeError("you cannot stream \"{}\" to shoutcast, use mp3", + mime_type); return SHOUT_PROTOCOL_ICY; } else if (StringIsEqual(value, "icecast1")) return SHOUT_PROTOCOL_XAUDIOCAST; else if (StringIsEqual(value, "icecast2")) return SHOUT_PROTOCOL_HTTP; else - throw FormatRuntimeError("shout protocol \"%s\" is not \"shoutcast\" or " - "\"icecast1\"or \"icecast2\"", - value); + throw FmtRuntimeError("shout protocol \"{}\" is not \"shoutcast\" or " + "\"icecast1\"or \"icecast2\"", + value); } inline @@ -309,16 +309,16 @@ HandleShoutError(shout_t *shout_conn, int err) case SHOUTERR_UNCONNECTED: case SHOUTERR_SOCKET: - throw FormatRuntimeError("Lost shout connection to %s:%i: %s", - shout_get_host(shout_conn), - shout_get_port(shout_conn), - shout_get_error(shout_conn)); + throw FmtRuntimeError("Lost shout connection to {}:{}: {}", + shout_get_host(shout_conn), + shout_get_port(shout_conn), + shout_get_error(shout_conn)); default: - throw FormatRuntimeError("connection to %s:%i error: %s", - shout_get_host(shout_conn), - shout_get_port(shout_conn), - shout_get_error(shout_conn)); + throw FmtRuntimeError("connection to {}:{} error: {}", + shout_get_host(shout_conn), + shout_get_port(shout_conn), + shout_get_error(shout_conn)); } } @@ -381,10 +381,10 @@ ShoutOpen(shout_t *shout_conn) break; default: - throw FormatRuntimeError("problem opening connection to shout server %s:%i: %s", - shout_get_host(shout_conn), - shout_get_port(shout_conn), - shout_get_error(shout_conn)); + throw FmtRuntimeError("problem opening connection to shout server {}:{}: {}", + shout_get_host(shout_conn), + shout_get_port(shout_conn), + shout_get_error(shout_conn)); } } diff --git a/src/output/plugins/WinmmOutputPlugin.cxx b/src/output/plugins/WinmmOutputPlugin.cxx index 34a5c40f7..b1692de4f 100644 --- a/src/output/plugins/WinmmOutputPlugin.cxx +++ b/src/output/plugins/WinmmOutputPlugin.cxx @@ -21,8 +21,8 @@ #include "../OutputAPI.hxx" #include "pcm/Buffer.hxx" #include "mixer/plugins/WinmmMixerPlugin.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "fs/AllocatedPath.hxx" -#include "util/RuntimeError.hxx" #include "util/StringCompare.hxx" #include @@ -91,7 +91,7 @@ MakeWaveOutError(MMRESULT result, const char *prefix) char buffer[256]; if (waveOutGetErrorTextA(result, buffer, std::size(buffer)) == MMSYSERR_NOERROR) - return FormatRuntimeError("%s: %s", prefix, buffer); + return FmtRuntimeError("{}: {}", prefix, buffer); else return std::runtime_error(prefix); } @@ -122,8 +122,8 @@ get_device_id(const char *device_name) UINT id = strtoul(device_name, &endptr, 0); if (endptr > device_name && *endptr == 0) { if (id >= numdevs) - throw FormatRuntimeError("device \"%s\" is not found", - device_name); + throw FmtRuntimeError("device \"{}\" is not found", + device_name); return id; } @@ -143,7 +143,7 @@ get_device_id(const char *device_name) return i; } - throw FormatRuntimeError("device \"%s\" is not found", device_name); + throw FmtRuntimeError("device \"{}\" is not found", device_name); } WinmmOutput::WinmmOutput(const ConfigBlock &block) diff --git a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx index 940c79f08..698d3b4f4 100644 --- a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx +++ b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx @@ -27,6 +27,7 @@ #include "output/OutputAPI.hxx" #include "lib/icu/Win32.hxx" #include "lib/fmt/AudioFormatFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "mixer/plugins/WasapiMixerPlugin.hxx" #include "output/Error.hxx" #include "pcm/Export.hxx" @@ -36,7 +37,6 @@ #include "thread/Thread.hxx" #include "util/AllocatedString.hxx" #include "util/Domain.hxx" -#include "util/RuntimeError.hxx" #include "util/ScopeExit.hxx" #include "util/StringBuffer.hxx" #include "win32/Com.hxx" @@ -806,8 +806,8 @@ WasapiOutput::ChooseDevice() if (!SafeSilenceTry([this, &id]() { id = std::stoul(device_config); })) { device = SearchDevice(*enumerator, device_config); if (!device) - throw FormatRuntimeError("Device '%s' not found", - device_config.c_str()); + throw FmtRuntimeError("Device '{}' not found", + device_config); } else device = GetDevice(*enumerator, id); } else { diff --git a/src/pcm/AudioParser.cxx b/src/pcm/AudioParser.cxx index dbe0265e6..ae5f83f7a 100644 --- a/src/pcm/AudioParser.cxx +++ b/src/pcm/AudioParser.cxx @@ -24,7 +24,7 @@ #include "AudioParser.hxx" #include "AudioFormat.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include @@ -46,7 +46,7 @@ ParseSampleRate(const char *src, bool mask, const char **endptr_r) if (endptr == src) { throw std::invalid_argument("Failed to parse the sample rate"); } else if (!audio_valid_sample_rate(value)) - throw FormatInvalidArgument("Invalid sample rate: %lu", value); + throw FmtInvalidArgument("Invalid sample rate: {}", value); *endptr_r = endptr; return value; @@ -100,8 +100,7 @@ ParseSampleFormat(const char *src, bool mask, const char **endptr_r) break; default: - throw FormatInvalidArgument("Invalid sample format: %lu", - value); + throw FmtInvalidArgument("Invalid sample format: {}", value); } assert(audio_valid_sample_format(sample_format)); @@ -125,8 +124,7 @@ ParseChannelCount(const char *src, bool mask, const char **endptr_r) if (endptr == src) throw std::invalid_argument("Failed to parse the channel count"); else if (!audio_valid_channel_count(value)) - throw FormatInvalidArgument("Invalid channel count: %u", - value); + throw FmtInvalidArgument("Invalid channel count: {}", value); *endptr_r = endptr; return value; @@ -152,8 +150,8 @@ ParseAudioFormat(const char *src, bool mask) src = endptr + 1; dest.channels = ParseChannelCount(src, mask, &src); if (*src != 0) - throw FormatInvalidArgument("Extra data after channel count: %s", - src); + throw FmtInvalidArgument("Extra data after channel count: {}", + src); return dest; } @@ -178,8 +176,8 @@ ParseAudioFormat(const char *src, bool mask) dest.channels = ParseChannelCount(src, mask, &src); if (*src != 0) - throw FormatInvalidArgument("Extra data after channel count: %s", - src); + throw FmtInvalidArgument("Extra data after channel count: {}", + src); assert(mask ? dest.IsMaskValid() diff --git a/src/pcm/ChannelsConverter.cxx b/src/pcm/ChannelsConverter.cxx index d10ae1c12..62177ce7d 100644 --- a/src/pcm/ChannelsConverter.cxx +++ b/src/pcm/ChannelsConverter.cxx @@ -19,7 +19,8 @@ #include "ChannelsConverter.hxx" #include "PcmChannels.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/AudioFormatFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/SpanCast.hxx" #include @@ -38,8 +39,8 @@ PcmChannelsConverter::Open(SampleFormat _format, break; default: - throw FormatRuntimeError("PCM channel conversion for %s is not implemented", - sample_format_to_string(_format)); + throw FmtRuntimeError("PCM channel conversion for {} is not implemented", + _format); } format = _format; diff --git a/src/pcm/CheckAudioFormat.cxx b/src/pcm/CheckAudioFormat.cxx index 2f6c45686..64ad64810 100644 --- a/src/pcm/CheckAudioFormat.cxx +++ b/src/pcm/CheckAudioFormat.cxx @@ -19,30 +19,30 @@ #include "CheckAudioFormat.hxx" #include "AudioFormat.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" void CheckSampleRate(unsigned long sample_rate) { if (!audio_valid_sample_rate(sample_rate)) - throw FormatRuntimeError("Invalid sample rate: %lu", - sample_rate); + throw FmtRuntimeError("Invalid sample rate: {}", + sample_rate); } void CheckSampleFormat(SampleFormat sample_format) { if (!audio_valid_sample_format(sample_format)) - throw FormatRuntimeError("Invalid sample format: %u", - unsigned(sample_format)); + throw FmtRuntimeError("Invalid sample format: {}", + unsigned(sample_format)); } void CheckChannelCount(unsigned channels) { if (!audio_valid_channel_count(channels)) - throw FormatRuntimeError("Invalid channel count: %u", - channels); + throw FmtRuntimeError("Invalid channel count: {}", + channels); } AudioFormat diff --git a/src/pcm/ConfiguredResampler.cxx b/src/pcm/ConfiguredResampler.cxx index c6d369a0c..b54934925 100644 --- a/src/pcm/ConfiguredResampler.cxx +++ b/src/pcm/ConfiguredResampler.cxx @@ -23,7 +23,7 @@ #include "config/Option.hxx" #include "config/Block.hxx" #include "config/Param.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "config.h" #ifdef ENABLE_LIBSAMPLERATE @@ -122,8 +122,8 @@ GetResamplerConfig(const ConfigData &config, ConfigBlock &buffer) return MigrateResamplerConfig(old_param, buffer); if (old_param != nullptr) - throw FormatRuntimeError("Cannot use both 'resampler' (line %d) and 'samplerate_converter' (line %d)", - block->line, old_param->line); + throw FmtRuntimeError("Cannot use both 'resampler' (line {}) and 'samplerate_converter' (line {})", + block->line, old_param->line); block->SetUsed(); return block; @@ -137,8 +137,8 @@ pcm_resampler_global_init(const ConfigData &config) const char *plugin_name = block->GetBlockValue("plugin"); if (plugin_name == nullptr) - throw FormatRuntimeError("'plugin' missing in line %d", - block->line); + throw FmtRuntimeError("'plugin' missing in line {}", + block->line); if (strcmp(plugin_name, "internal") == 0) { selected_resampler = SelectedResampler::FALLBACK; @@ -153,8 +153,8 @@ pcm_resampler_global_init(const ConfigData &config) pcm_resample_lsr_global_init(*block); #endif } else { - throw FormatRuntimeError("No such resampler plugin: %s", - plugin_name); + throw FmtRuntimeError("No such resampler plugin: {}", + plugin_name); } } diff --git a/src/pcm/FormatConverter.cxx b/src/pcm/FormatConverter.cxx index 07c9751e7..b623f124d 100644 --- a/src/pcm/FormatConverter.cxx +++ b/src/pcm/FormatConverter.cxx @@ -19,7 +19,8 @@ #include "FormatConverter.hxx" #include "PcmFormat.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/AudioFormatFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include @@ -36,9 +37,8 @@ PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format) case SampleFormat::S8: case SampleFormat::DSD: - throw FormatRuntimeError("PCM conversion from %s to %s is not implemented", - sample_format_to_string(_src_format), - sample_format_to_string(_dest_format)); + throw FmtRuntimeError("PCM conversion from {} to {} is not implemented", + _src_format, _dest_format); case SampleFormat::S16: case SampleFormat::S24_P32: diff --git a/src/pcm/LibsamplerateResampler.cxx b/src/pcm/LibsamplerateResampler.cxx index 81ae37454..f198395eb 100644 --- a/src/pcm/LibsamplerateResampler.cxx +++ b/src/pcm/LibsamplerateResampler.cxx @@ -19,8 +19,8 @@ #include "LibsamplerateResampler.hxx" #include "config/Block.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/ASCII.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/SpanCast.hxx" #include "Log.hxx" @@ -69,8 +69,8 @@ pcm_resample_lsr_global_init(const ConfigBlock &block) { const char *converter = block.GetBlockValue("type", "2"); if (!lsr_parse_converter(converter)) - throw FormatRuntimeError("unknown samplerate converter '%s'", - converter); + throw FmtRuntimeError("unknown samplerate converter '{}'", + converter); FmtDebug(libsamplerate_domain, "libsamplerate converter '{}'", @@ -93,8 +93,8 @@ LibsampleratePcmResampler::Open(AudioFormat &af, unsigned new_sample_rate) int src_error; state = src_new(lsr_converter, channels, &src_error); if (!state) - throw FormatRuntimeError("libsamplerate initialization has failed: %s", - src_strerror(src_error)); + throw FmtRuntimeError("libsamplerate initialization has failed: {}", + src_strerror(src_error)); memset(&data, 0, sizeof(data)); @@ -138,8 +138,8 @@ LibsampleratePcmResampler::Resample2(std::span src) int result = src_process(state, &data); if (result != 0) - throw FormatRuntimeError("libsamplerate has failed: %s", - src_strerror(result)); + throw FmtRuntimeError("libsamplerate has failed: {}", + src_strerror(result)); return {data.data_out, size_t(data.output_frames_gen * channels)}; } diff --git a/src/pcm/SoxrResampler.cxx b/src/pcm/SoxrResampler.cxx index 148669045..463dc09b3 100644 --- a/src/pcm/SoxrResampler.cxx +++ b/src/pcm/SoxrResampler.cxx @@ -20,7 +20,7 @@ #include "SoxrResampler.hxx" #include "AudioFormat.hxx" #include "config/Block.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -100,18 +100,17 @@ SoxrParsePrecision(unsigned value) { case 32: break; default: - throw FormatInvalidArgument( - "soxr converter invalid precision : %d [16|20|24|28|32]", value); + throw FmtInvalidArgument("soxr converter invalid precision: {} [16|20|24|28|32]", + value); } return value; } static double SoxrParsePhaseResponse(unsigned value) { - if (value > 100) { - throw FormatInvalidArgument( - "soxr converter invalid phase_respons : %d (0-100)", value); - } + if (value > 100) + throw FmtInvalidArgument("soxr converter invalid phase_respons : {} (0-100)", + value); return double(value); } @@ -120,15 +119,13 @@ static double SoxrParsePassbandEnd(const char *svalue) { char *endptr; double value = strtod(svalue, &endptr); - if (svalue == endptr || *endptr != 0) { - throw FormatInvalidArgument( - "soxr converter passband_end value not a number: %s", svalue); - } + if (svalue == endptr || *endptr != 0) + throw FmtInvalidArgument("soxr converter passband_end value not a number: {}", + svalue); - if (value < 1 || value > 100) { - throw FormatInvalidArgument( - "soxr converter invalid passband_end : %s (1-100%%)", svalue); - } + if (value < 1 || value > 100) + throw FmtInvalidArgument("soxr converter invalid passband_end: {} (1-100%)", + svalue); return value / 100.0; } @@ -137,15 +134,13 @@ static double SoxrParseStopbandBegin(const char *svalue) { char *endptr; double value = strtod(svalue, &endptr); - if (svalue == endptr || *endptr != 0) { - throw FormatInvalidArgument( - "soxr converter stopband_begin value not a number: %s", svalue); - } + if (svalue == endptr || *endptr != 0) + throw FmtInvalidArgument("soxr converter stopband_begin value not a number: {}", + svalue); - if (value < 100 || value > 199) { - throw FormatInvalidArgument( - "soxr converter invalid stopband_begin : %s (100-150%%)", svalue); - } + if (value < 100 || value > 199) + throw FmtInvalidArgument("soxr converter invalid stopband_begin: {} (100-150%)", + svalue); return value / 100.0; } @@ -155,14 +150,13 @@ SoxrParseAttenuation(const char *svalue) { char *endptr; double value = strtod(svalue, &endptr); if (svalue == endptr || *endptr != 0) { - throw FormatInvalidArgument( - "soxr converter attenuation value not a number: %s", svalue); + throw FmtInvalidArgument("soxr converter attenuation value not a number: {}", + svalue); } - if (value < 0 || value > 30) { - throw FormatInvalidArgument( - "soxr converter invalid attenuation : %s (0-30dB))", svalue); - } + if (value < 0 || value > 30) + throw FmtInvalidArgument("soxr converter invalid attenuation: {} (0-30dB))", + svalue); return 1 / std::pow(10, value / 10.0); } @@ -176,8 +170,8 @@ pcm_resample_soxr_global_init(const ConfigBlock &block) if (recipe == SOXR_INVALID_RECIPE) { assert(quality_string != nullptr); - throw FormatRuntimeError("unknown quality setting '%s' in line %d", - quality_string, block.line); + throw FmtRuntimeError("unknown quality setting '{}' in line {}", + quality_string, block.line); } else if (recipe == SOXR_CUSTOM_RECIPE) { // used to preset possible internal flags, like SOXR_RESET_ON_CLEAR soxr_quality = soxr_quality_spec(SOXR_DEFAULT_RECIPE, 0); @@ -222,8 +216,8 @@ SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate) af.channels, &e, p_soxr_io, &soxr_quality, &soxr_runtime); if (soxr == nullptr) - throw FormatRuntimeError("soxr initialization has failed: %s", - e); + throw FmtRuntimeError("soxr initialization has failed: {}", + e); FmtDebug(soxr_domain, "soxr engine '{}'", soxr_engine(soxr)); if (soxr_use_custom_recipe) @@ -284,7 +278,7 @@ SoxrPcmResampler::Resample(std::span src) soxr_error_t e = soxr_process(soxr, src.data(), n_frames, &i_done, output_buffer, o_frames, &o_done); if (e != nullptr) - throw FormatRuntimeError("soxr error: %s", e); + throw FmtRuntimeError("soxr error: {}", e); return { (const std::byte *)output_buffer, o_done * frame_size }; } @@ -301,7 +295,7 @@ SoxrPcmResampler::Flush() soxr_error_t e = soxr_process(soxr, nullptr, 0, nullptr, output_buffer, o_frames, &o_done); if (e != nullptr) - throw FormatRuntimeError("soxr error: %s", e); + throw FmtRuntimeError("soxr error: {}", e); if (o_done == 0) /* flush complete */ diff --git a/src/pcm/Volume.cxx b/src/pcm/Volume.cxx index a3d8a9856..7e918f4a7 100644 --- a/src/pcm/Volume.cxx +++ b/src/pcm/Volume.cxx @@ -20,7 +20,8 @@ #include "Volume.hxx" #include "Silence.hxx" #include "Traits.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/AudioFormatFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/TransformN.hxx" #include "Dither.cxx" // including the .cxx file to get inlined templates @@ -154,8 +155,8 @@ PcmVolume::Open(SampleFormat _format, bool allow_convert) switch (_format) { case SampleFormat::UNDEFINED: - throw FormatRuntimeError("Software volume for %s is not implemented", - sample_format_to_string(_format)); + throw FmtRuntimeError("Software volume for {} is not implemented", + _format); case SampleFormat::S8: break; diff --git a/src/pcm/meson.build b/src/pcm/meson.build index a8dff1d7a..04cb3f536 100644 --- a/src/pcm/meson.build +++ b/src/pcm/meson.build @@ -30,6 +30,7 @@ pcm_basic = static_library( include_directories: inc, dependencies: [ util_dep, + fmt_dep, ], ) diff --git a/src/playlist/plugins/FlacPlaylistPlugin.cxx b/src/playlist/plugins/FlacPlaylistPlugin.cxx index aedb1926d..8267b49db 100644 --- a/src/playlist/plugins/FlacPlaylistPlugin.cxx +++ b/src/playlist/plugins/FlacPlaylistPlugin.cxx @@ -28,9 +28,9 @@ #include "../MemorySongEnumerator.hxx" #include "lib/xiph/FlacMetadataChain.hxx" #include "lib/xiph/FlacMetadataIterator.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "song/DetachedSong.hxx" #include "input/InputStream.hxx" -#include "util/RuntimeError.hxx" #include @@ -67,8 +67,8 @@ flac_playlist_open_stream(InputStreamPtr &&is) { FlacMetadataChain chain; if (!chain.Read(*is)) - throw FormatRuntimeError("Failed to read FLAC metadata: %s", - chain.GetStatusString()); + throw FmtRuntimeError("Failed to read FLAC metadata: {}", + chain.GetStatusString()); FlacMetadataIterator iterator((FLAC__Metadata_Chain *)chain); diff --git a/src/song/Filter.cxx b/src/song/Filter.cxx index 37edad653..03724941b 100644 --- a/src/song/Filter.cxx +++ b/src/song/Filter.cxx @@ -29,8 +29,8 @@ #include "pcm/AudioParser.hxx" #include "tag/ParseName.hxx" #include "time/ISO8601.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/CharUtil.hxx" -#include "util/RuntimeError.hxx" #include "util/StringCompare.hxx" #include "util/StringStrip.hxx" #include "util/ASCII.hxx" @@ -160,8 +160,7 @@ ExpectFilterType(const char *&s) const auto type = locate_parse_type(name.c_str()); if (type == TAG_NUM_OF_ITEM_TYPES) - throw FormatRuntimeError("Unknown filter type: %s", - name.c_str()); + throw FmtRuntimeError("Unknown filter type: {}", name); return type; } diff --git a/src/storage/Configured.cxx b/src/storage/Configured.cxx index fcb0e2976..145b52717 100644 --- a/src/storage/Configured.cxx +++ b/src/storage/Configured.cxx @@ -24,7 +24,7 @@ #include "config/Data.hxx" #include "fs/StandardDirectory.hxx" #include "fs/CheckFile.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/UriExtract.hxx" static std::unique_ptr @@ -32,7 +32,7 @@ CreateConfiguredStorageUri(EventLoop &event_loop, const char *uri) { auto storage = CreateStorageURI(event_loop, uri); if (storage == nullptr) - throw FormatRuntimeError("Unrecognized storage URI: %s", uri); + throw FmtRuntimeError("Unrecognized storage URI: {}", uri); return storage; } diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 393fdfc71..20b9da70d 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -30,12 +30,12 @@ #include "lib/curl/Handler.hxx" #include "lib/curl/Escape.hxx" #include "lib/expat/ExpatParser.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "fs/Traits.hxx" #include "event/InjectEvent.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" #include "util/ASCII.hxx" -#include "util/RuntimeError.hxx" #include "util/SpanCast.hxx" #include "util/StringCompare.hxx" #include "util/StringFormat.hxx" @@ -302,8 +302,8 @@ private: /* virtual methods from CurlResponseHandler */ void OnHeaders(unsigned status, Curl::Headers &&headers) final { if (status != 207) - throw FormatRuntimeError("Status %d from WebDAV server; expected \"207 Multi-Status\"", - status); + throw FmtRuntimeError("Status {} from WebDAV server; expected \"207 Multi-Status\"", + status); if (!IsXmlContentType(headers)) throw std::runtime_error("Unexpected Content-Type from WebDAV server"); diff --git a/src/storage/plugins/UdisksStorage.cxx b/src/storage/plugins/UdisksStorage.cxx index 36c0ae126..577378f2f 100644 --- a/src/storage/plugins/UdisksStorage.cxx +++ b/src/storage/plugins/UdisksStorage.cxx @@ -23,6 +23,7 @@ #include "storage/StorageInterface.hxx" #include "storage/FileInfo.hxx" #include "lib/fmt/ExceptionFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/dbus/Glue.hxx" #include "lib/dbus/AsyncRequest.hxx" #include "lib/dbus/Message.hxx" @@ -38,7 +39,6 @@ #include "fs/AllocatedPath.hxx" #include "util/Domain.hxx" #include "util/StringCompare.hxx" -#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -180,8 +180,8 @@ UdisksStorage::OnListReply(ODBus::Message reply) noexcept }); if (dbus_path.empty()) - throw FormatRuntimeError("No such UDisks2 object: %s", - id.c_str()); + throw FmtRuntimeError("No such UDisks2 object: {}", + id); if (!mount_point.empty()) { /* already mounted: don't attempt to mount diff --git a/src/tag/Config.cxx b/src/tag/Config.cxx index ddf622dd5..ae9e2f616 100644 --- a/src/tag/Config.cxx +++ b/src/tag/Config.cxx @@ -22,8 +22,8 @@ #include "ParseName.hxx" #include "config/Data.hxx" #include "config/Option.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "util/ASCII.hxx" -#include "util/RuntimeError.hxx" #include "util/IterableSplitString.hxx" #include "util/StringCompare.hxx" #include "util/StringStrip.hxx" @@ -59,8 +59,8 @@ TagLoadConfig(const ConfigData &config) const auto type = tag_name_parse_i(name); if (type == TAG_NUM_OF_ITEM_TYPES) - throw FormatRuntimeError("error parsing metadata item \"%s\"", - name); + throw FmtRuntimeError("error parsing metadata item \"{}\"", + name); if (plus) global_tag_mask.Set(type); diff --git a/src/tag/meson.build b/src/tag/meson.build index 9f564db6e..b643e1cf5 100644 --- a/src/tag/meson.build +++ b/src/tag/meson.build @@ -58,6 +58,7 @@ tag = static_library( tag_sources, include_directories: inc, dependencies: [ + fmt_dep, libid3tag_dep, ], ) diff --git a/src/unix/Daemon.cxx b/src/unix/Daemon.cxx index f6db298ee..719a6b688 100644 --- a/src/unix/Daemon.cxx +++ b/src/unix/Daemon.cxx @@ -20,9 +20,9 @@ #include "config.h" #include "Daemon.hxx" #include "lib/fmt/PathFormatter.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "lib/fmt/SystemError.hxx" #include "fs/AllocatedPath.hxx" -#include "util/RuntimeError.hxx" #ifndef _WIN32 #include "PidFile.hxx" @@ -217,7 +217,7 @@ daemonize_init(const char *user, const char *group, AllocatedPath &&_pidfile) if (user) { struct passwd *pwd = getpwnam(user); if (pwd == nullptr) - throw FormatRuntimeError("no such user \"%s\"", user); + throw FmtRuntimeError("no such user \"{}\"", user); user_uid = pwd->pw_uid; user_gid = pwd->pw_gid; @@ -231,8 +231,7 @@ daemonize_init(const char *user, const char *group, AllocatedPath &&_pidfile) if (group) { struct group *grp = getgrnam(group); if (grp == nullptr) - throw FormatRuntimeError("no such group \"%s\"", - group); + throw FmtRuntimeError("no such group \"{}\"", group); user_gid = grp->gr_gid; had_group = true; } diff --git a/src/zeroconf/avahi/Helper.cxx b/src/zeroconf/avahi/Helper.cxx index e7da4138a..c6df1b0a4 100644 --- a/src/zeroconf/avahi/Helper.cxx +++ b/src/zeroconf/avahi/Helper.cxx @@ -22,7 +22,7 @@ #include "lib/avahi/ErrorHandler.hxx" #include "lib/avahi/Publisher.hxx" #include "lib/avahi/Service.hxx" -#include "util/RuntimeError.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "Log.hxx" #include @@ -56,8 +56,8 @@ AvahiInit(EventLoop &event_loop, const char *service_name, const char *service_type, unsigned port) { if (!avahi_is_valid_service_name(service_name)) - throw FormatRuntimeError("Invalid zeroconf_name \"%s\"", - service_name); + throw FmtRuntimeError("Invalid zeroconf_name \"{}\"", + service_name); auto client = shared_avahi_client.lock(); if (!client) diff --git a/test/read_conf.cxx b/test/read_conf.cxx index b6c2ef0a7..4f8cb59e9 100644 --- a/test/read_conf.cxx +++ b/test/read_conf.cxx @@ -20,10 +20,10 @@ #include "config/Data.hxx" #include "config/Param.hxx" #include "config/File.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "fs/Path.hxx" #include "fs/NarrowPath.hxx" #include "util/PrintException.hxx" -#include "util/RuntimeError.hxx" #include #include @@ -40,14 +40,14 @@ try { const auto option = ParseConfigOptionName(name); if (option == ConfigOption::MAX) - throw FormatRuntimeError("Unknown setting: %s", name); + throw FmtRuntimeError("Unknown setting: {}", name); ConfigData config; ReadConfigFile(config, config_path); const auto *param = config.GetParam(option); if (param == nullptr) - throw FormatRuntimeError("No such setting: %s", name); + throw FmtRuntimeError("No such setting: {}", name); printf("%s\n", param->value.c_str()); return EXIT_SUCCESS; diff --git a/test/run_filter.cxx b/test/run_filter.cxx index 0546001ee..1c9e0a814 100644 --- a/test/run_filter.cxx +++ b/test/run_filter.cxx @@ -19,6 +19,7 @@ #include "ConfigGlue.hxx" #include "ReadFrames.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "fs/Path.hxx" #include "fs/NarrowPath.hxx" #include "filter/LoadOne.hxx" @@ -31,7 +32,6 @@ #include "system/Error.hxx" #include "io/FileDescriptor.hxx" #include "util/StringBuffer.hxx" -#include "util/RuntimeError.hxx" #include "util/PrintException.hxx" #include @@ -48,8 +48,8 @@ LoadFilter(const ConfigData &config, const char *name) const auto *param = config.FindBlock(ConfigBlockOption::AUDIO_FILTER, "name", name); if (param == nullptr) - throw FormatRuntimeError("No such configured filter: %s", - name); + throw FmtRuntimeError("No such configured filter: {}", + name); return filter_configured_new(*param); } diff --git a/test/run_output.cxx b/test/run_output.cxx index 39a134135..f33748c2b 100644 --- a/test/run_output.cxx +++ b/test/run_output.cxx @@ -21,6 +21,7 @@ #include "output/Registry.hxx" #include "output/OutputPlugin.hxx" #include "ConfigGlue.hxx" +#include "lib/fmt/RuntimeError.hxx" #include "event/Thread.hxx" #include "fs/Path.hxx" #include "fs/NarrowPath.hxx" @@ -29,7 +30,6 @@ #include "cmdline/OptionDef.hxx" #include "cmdline/OptionParser.hxx" #include "util/StringBuffer.hxx" -#include "util/RuntimeError.hxx" #include "util/ScopeExit.hxx" #include "util/StaticFifoBuffer.hxx" #include "util/PrintException.hxx" @@ -95,8 +95,8 @@ LoadAudioOutput(const ConfigData &config, EventLoop &event_loop, const auto *block = config.FindBlock(ConfigBlockOption::AUDIO_OUTPUT, "name", name); if (block == nullptr) - throw FormatRuntimeError("No such configured audio output: %s", - name); + throw FmtRuntimeError("No such configured audio output: {}", + name); const char *plugin_name = block->GetBlockValue("type"); if (plugin_name == nullptr) @@ -104,8 +104,8 @@ LoadAudioOutput(const ConfigData &config, EventLoop &event_loop, const auto *plugin = AudioOutputPlugin_get(plugin_name); if (plugin == nullptr) - throw FormatRuntimeError("No such audio output plugin: %s", - plugin_name); + throw FmtRuntimeError("No such audio output plugin: {}", + plugin_name); return std::unique_ptr(ao_plugin_init(event_loop, *plugin, *block));