From 0440c41cbac0857eaab1220e3b0852c61bfc794a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 21 May 2021 20:35:29 +0200 Subject: [PATCH] client/Response: add method Fmt() based on libfmt --- src/SongPrint.cxx | 43 +++++++------ src/Stats.cxx | 30 ++++----- src/TagPrint.cxx | 17 ++--- src/TimePrint.cxx | 4 +- src/client/Idle.cxx | 4 +- src/client/Response.cxx | 16 +++-- src/client/Response.hxx | 20 ++++++ src/command/AllCommands.cxx | 6 +- src/command/FileCommands.cxx | 40 ++++-------- src/command/FingerprintCommands.cxx | 6 +- src/command/MessageCommands.cxx | 8 ++- src/command/NeighborCommands.cxx | 10 +-- src/command/OtherCommands.cxx | 14 +++-- src/command/PartitionCommands.cxx | 4 +- src/command/PlayerCommands.cxx | 96 +++++++++++++++-------------- src/command/PlaylistCommands.cxx | 4 +- src/command/QueueCommands.cxx | 4 +- src/command/StorageCommands.cxx | 26 +++----- src/db/Count.cxx | 8 ++- src/db/DatabasePrint.cxx | 22 ++++--- src/db/meson.build | 1 + src/decoder/DecoderPrint.cxx | 8 ++- src/ls.cxx | 5 +- src/output/Print.cxx | 19 +++--- src/output/meson.build | 3 + src/queue/QueuePrint.cxx | 14 +++-- src/sticker/Print.cxx | 4 +- 27 files changed, 241 insertions(+), 195 deletions(-) diff --git a/src/SongPrint.cxx b/src/SongPrint.cxx index d6e18e77a..f19c89a81 100644 --- a/src/SongPrint.cxx +++ b/src/SongPrint.cxx @@ -27,6 +27,8 @@ #include "time/ChronoUtil.hxx" #include "util/UriUtil.hxx" +#include + #define SONG_FILE "file: " static void @@ -42,14 +44,15 @@ song_print_uri(Response &r, const char *uri, bool base) noexcept uri = allocated.c_str(); } - r.Format(SONG_FILE "%s\n", uri); + r.Fmt(FMT_STRING(SONG_FILE "{}\n"), uri); } void song_print_uri(Response &r, const LightSong &song, bool base) noexcept { if (!base && song.directory != nullptr) - r.Format(SONG_FILE "%s/%s\n", song.directory, song.uri); + r.Fmt(FMT_STRING(SONG_FILE "{}/{}\n"), + song.directory, song.uri); else song_print_uri(r, song.uri, base); } @@ -67,15 +70,15 @@ PrintRange(Response &r, SongTime start_time, SongTime end_time) noexcept const unsigned end_ms = end_time.ToMS(); if (end_ms > 0) - r.Format("Range: %u.%03u-%u.%03u\n", - start_ms / 1000, - start_ms % 1000, - end_ms / 1000, - end_ms % 1000); + r.Fmt(FMT_STRING("Range: {}.{:03}-{}.{:03}\n"), + start_ms / 1000, + start_ms % 1000, + end_ms / 1000, + end_ms % 1000); else if (start_ms > 0) - r.Format("Range: %u.%03u-\n", - start_ms / 1000, - start_ms % 1000); + r.Fmt(FMT_STRING("Range: {}.{:03}-\n"), + start_ms / 1000, + start_ms % 1000); } void @@ -89,16 +92,16 @@ song_print_info(Response &r, const LightSong &song, bool base) noexcept time_print(r, "Last-Modified", song.mtime); if (song.audio_format.IsDefined()) - r.Format("Format: %s\n", ToString(song.audio_format).c_str()); + r.Fmt(FMT_STRING("Format: {}\n"), ToString(song.audio_format)); tag_print_values(r, song.tag); const auto duration = song.GetDuration(); if (!duration.IsNegative()) - r.Format("Time: %i\n" - "duration: %1.3f\n", - duration.RoundS(), - duration.ToDoubleS()); + r.Fmt(FMT_STRING("Time: {}\n" + "duration: {:1.3}\n"), + duration.RoundS(), + duration.ToDoubleS()); } void @@ -112,14 +115,14 @@ song_print_info(Response &r, const DetachedSong &song, bool base) noexcept time_print(r, "Last-Modified", song.GetLastModified()); if (const auto &f = song.GetAudioFormat(); f.IsDefined()) - r.Format("Format: %s\n", ToString(f).c_str()); + r.Fmt(FMT_STRING("Format: {}\n"), ToString(f)); tag_print_values(r, song.GetTag()); const auto duration = song.GetDuration(); if (!duration.IsNegative()) - r.Format("Time: %i\n" - "duration: %1.3f\n", - duration.RoundS(), - duration.ToDoubleS()); + r.Fmt(FMT_STRING("Time: {}\n" + "duration: {:1.3}\n"), + duration.RoundS(), + duration.ToDoubleS()); } diff --git a/src/Stats.cxx b/src/Stats.cxx index 4a383726f..077c6b49d 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -34,6 +34,8 @@ #include "system/Clock.hxx" #endif +#include + #include #ifndef _WIN32 @@ -97,19 +99,19 @@ db_stats_print(Response &r, const Database &db) unsigned total_duration_s = std::chrono::duration_cast(stats.total_duration).count(); - r.Format("artists: %u\n" - "albums: %u\n" - "songs: %u\n" - "db_playtime: %u\n", - stats.artist_count, - stats.album_count, - stats.song_count, - total_duration_s); + r.Fmt(FMT_STRING("artists: {}\n" + "albums: {}\n" + "songs: {}\n" + "db_playtime: {}\n"), + stats.artist_count, + stats.album_count, + stats.song_count, + total_duration_s); const auto update_stamp = db.GetUpdateStamp(); if (!IsNegative(update_stamp)) - r.Format("db_update: %lu\n", - (unsigned long)std::chrono::system_clock::to_time_t(update_stamp)); + r.Fmt(FMT_STRING("db_update: {}\n"), + std::chrono::system_clock::to_time_t(update_stamp)); } #endif @@ -123,10 +125,10 @@ stats_print(Response &r, const Partition &partition) const auto uptime = std::chrono::steady_clock::now() - start_time; #endif - r.Format("uptime: %u\n" - "playtime: %lu\n", - (unsigned)std::chrono::duration_cast(uptime).count(), - lround(partition.pc.GetTotalPlayTime().count())); + r.Fmt(FMT_STRING("uptime: {}\n" + "playtime: {}\n"), + std::chrono::duration_cast(uptime).count(), + lround(partition.pc.GetTotalPlayTime().count())); #ifdef ENABLE_DATABASE const Database *db = partition.instance.GetDatabase(); diff --git a/src/TagPrint.cxx b/src/TagPrint.cxx index ec426c245..7b338751a 100644 --- a/src/TagPrint.cxx +++ b/src/TagPrint.cxx @@ -23,26 +23,27 @@ #include "client/Response.hxx" #include "util/StringView.hxx" +#include + void tag_print_types(Response &r) noexcept { const auto tag_mask = global_tag_mask & r.GetTagMask(); for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) if (tag_mask.Test(TagType(i))) - r.Format("tagtype: %s\n", tag_item_names[i]); + r.Fmt(FMT_STRING("tagtype: {}\n"), tag_item_names[i]); } void tag_print(Response &r, TagType type, StringView value) noexcept { - r.Format("%s: %.*s\n", tag_item_names[type], - int(value.size), value.data); + r.Fmt(FMT_STRING("{}: {}\n"), tag_item_names[type], value); } void tag_print(Response &r, TagType type, const char *value) noexcept { - r.Format("%s: %s\n", tag_item_names[type], value); + r.Fmt(FMT_STRING("{}: {}\n"), tag_item_names[type], value); } void @@ -58,10 +59,10 @@ void tag_print(Response &r, const Tag &tag) noexcept { if (!tag.duration.IsNegative()) - r.Format("Time: %i\n" - "duration: %1.3f\n", - tag.duration.RoundS(), - tag.duration.ToDoubleS()); + r.Fmt(FMT_STRING("Time: {}\n" + "duration: {:1.3}\n"), + tag.duration.RoundS(), + tag.duration.ToDoubleS()); tag_print_values(r, tag); } diff --git a/src/TimePrint.cxx b/src/TimePrint.cxx index 7e9a3dc36..242718c80 100644 --- a/src/TimePrint.cxx +++ b/src/TimePrint.cxx @@ -21,6 +21,8 @@ #include "client/Response.hxx" #include "time/ISO8601.hxx" +#include + void time_print(Response &r, const char *name, std::chrono::system_clock::time_point t) @@ -33,5 +35,5 @@ time_print(Response &r, const char *name, return; } - r.Format("%s: %s\n", name, s.c_str()); + r.Fmt(FMT_STRING("{}: {}\n"), name, s); } diff --git a/src/client/Idle.cxx b/src/client/Idle.cxx index 658893a1d..3f54e583f 100644 --- a/src/client/Idle.cxx +++ b/src/client/Idle.cxx @@ -22,6 +22,8 @@ #include "Response.hxx" #include "Idle.hxx" +#include + #include static void @@ -30,7 +32,7 @@ WriteIdleResponse(Response &r, unsigned flags) noexcept const char *const*idle_names = idle_get_names(); for (unsigned i = 0; idle_names[i]; ++i) { if (flags & (1 << i)) - r.Format("changed: %s\n", idle_names[i]); + r.Fmt(FMT_STRING("changed: {}\n"), idle_names[i]); } r.Write("OK\n"); diff --git a/src/client/Response.cxx b/src/client/Response.cxx index b582d6bbc..fe2c8a500 100644 --- a/src/client/Response.cxx +++ b/src/client/Response.cxx @@ -22,6 +22,8 @@ #include "util/FormatString.hxx" #include "util/AllocatedString.hxx" +#include + TagMask Response::GetTagMask() const noexcept { @@ -56,17 +58,21 @@ Response::Format(const char *fmt, ...) noexcept return success; } +bool +Response::VFmt(fmt::string_view format_str, fmt::format_args args) noexcept +{ + fmt::memory_buffer buffer; + fmt::vformat_to(buffer, format_str, args); + return Write(buffer.data(), buffer.size()); +} + bool Response::WriteBinary(ConstBuffer payload) noexcept { assert(payload.size <= client.binary_limit); return -#ifdef _WIN32 - Format("binary: %lu\n", (unsigned long)payload.size) && -#else - Format("binary: %zu\n", payload.size) && -#endif + Fmt("binary: {}\n", payload.size) && Write(payload.data, payload.size) && Write("\n"); } diff --git a/src/client/Response.hxx b/src/client/Response.hxx index 4c7e40e8a..537001aae 100644 --- a/src/client/Response.hxx +++ b/src/client/Response.hxx @@ -23,6 +23,11 @@ #include "protocol/Ack.hxx" #include "util/Compiler.h" +#include +#if FMT_VERSION < 70000 +#include +#endif + #include #include @@ -79,6 +84,21 @@ public: gcc_printf(2,3) bool Format(const char *fmt, ...) noexcept; + bool VFmt(fmt::string_view format_str, fmt::format_args args) noexcept; + + template + bool Fmt(const S &format_str, Args&&... args) noexcept { +#if FMT_VERSION >= 70000 + return VFmt(fmt::to_string_view(format_str), + fmt::make_args_checked(format_str, + args...)); +#else + /* expensive fallback for older libfmt versions */ + const auto result = fmt::format(format_str, args...); + return Write(result.data(), result.size()); +#endif + } + /** * Write a binary chunk; this writes the "binary" line, the * given chunk and the trailing newline. diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx index 9a36b9bdb..ab1d72f2d 100644 --- a/src/command/AllCommands.cxx +++ b/src/command/AllCommands.cxx @@ -48,6 +48,8 @@ #include "StickerCommands.hxx" #endif +#include + #include #include @@ -253,7 +255,7 @@ PrintAvailableCommands(Response &r, const Partition &partition, if (cmd->permission == (permission & cmd->permission) && command_available(partition, cmd)) - r.Format("command: %s\n", cmd->cmd); + r.Fmt(FMT_STRING("command: {}\n"), cmd->cmd); } return CommandResult::OK; @@ -266,7 +268,7 @@ PrintUnavailableCommands(Response &r, unsigned permission) noexcept const struct command *cmd = &i; if (cmd->permission != (permission & cmd->permission)) - r.Format("command: %s\n", cmd->cmd); + r.Fmt(FMT_STRING("command: {}\n"), cmd->cmd); } return CommandResult::OK; diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index 1c8b6ee28..0ccf494db 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -17,8 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define __STDC_FORMAT_MACROS /* for PRIu64 */ - #include "config.h" #include "FileCommands.hxx" #include "Request.hxx" @@ -43,9 +41,10 @@ #include "thread/Mutex.hxx" #include "Log.hxx" +#include + #include #include -#include /* for PRIu64 */ gcc_pure static bool @@ -61,13 +60,6 @@ skip_path(Path name_fs) noexcept return name_fs.HasNewline(); } -#if defined(_WIN32) && GCC_CHECK_VERSION(4,6) -/* PRIu64 causes bogus compiler warning */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat" -#pragma GCC diagnostic ignored "-Wformat-extra-args" -#endif - CommandResult handle_listfiles_local(Response &r, Path path_fs) { @@ -88,12 +80,12 @@ handle_listfiles_local(Response &r, Path path_fs) continue; if (fi.IsRegular()) - r.Format("file: %s\n" - "size: %" PRIu64 "\n", - name_utf8.c_str(), - fi.GetSize()); + r.Fmt(FMT_STRING("file: {}\n" + "size: {}\n"), + name_utf8, + fi.GetSize()); else if (fi.IsDirectory()) - r.Format("directory: %s\n", name_utf8.c_str()); + r.Fmt(FMT_STRING("directory: {}\n"), name_utf8); else continue; @@ -135,9 +127,7 @@ public: void OnPair(StringView key, StringView value) noexcept override { if (IsValidName(key) && IsValidValue(value)) - response.Format("%.*s: %.*s\n", - int(key.size), key.data, - int(value.size), value.data); + response.Fmt(FMT_STRING("{}: {}\n"), key, value); } }; @@ -228,11 +218,7 @@ read_stream_art(Response &r, const char *uri, size_t offset) read_size = is->Read(lock, buffer.get(), buffer_size); } -#ifdef _WIN32 - r.Format("size: %lu\n", (unsigned long)art_file_size); -#else - r.Format("size: %" PRIoffset "\n", art_file_size); -#endif + r.Fmt(FMT_STRING("size: {}\n"), art_file_size); r.WriteBinary({buffer.get(), read_size}); @@ -315,14 +301,10 @@ public: return; } -#ifdef _WIN32 - response.Format("size: %lu\n", (unsigned long)buffer.size); -#else - response.Format("size: %zu\n", buffer.size); -#endif + response.Fmt(FMT_STRING("size: {}\n"), buffer.size); if (mime_type != nullptr) - response.Format("type: %s\n", mime_type); + response.Fmt(FMT_STRING("type: {}\n"), mime_type); buffer.size -= offset; diff --git a/src/command/FingerprintCommands.cxx b/src/command/FingerprintCommands.cxx index 6daaeb830..d4b0e7230 100644 --- a/src/command/FingerprintCommands.cxx +++ b/src/command/FingerprintCommands.cxx @@ -37,6 +37,8 @@ #include "util/MimeType.hxx" #include "util/UriExtract.hxx" +#include + class GetChromaprintCommand final : public ThreadBackgroundCommand, ChromaprintDecoderClient, InputStreamHandler { @@ -60,8 +62,8 @@ protected: void Run() override; void SendResponse(Response &r) noexcept override { - r.Format("chromaprint: %s\n", - GetFingerprint().c_str()); + r.Fmt(FMT_STRING("chromaprint: {}\n"), + GetFingerprint()); } void CancelThread() noexcept override { diff --git a/src/command/MessageCommands.cxx b/src/command/MessageCommands.cxx index 2da939b82..0bbd0e12c 100644 --- a/src/command/MessageCommands.cxx +++ b/src/command/MessageCommands.cxx @@ -25,6 +25,8 @@ #include "util/ConstBuffer.hxx" #include "Partition.hxx" +#include + #include #include #include @@ -85,7 +87,7 @@ handle_channels(Client &client, [[maybe_unused]] Request args, Response &r) } for (const auto &channel : channels) - r.Format("channel: %s\n", channel.c_str()); + r.Fmt(FMT_STRING("channel: {}\n"), channel); return CommandResult::OK; } @@ -97,8 +99,8 @@ handle_read_messages(Client &client, assert(args.empty()); client.ConsumeMessages([&r](const auto &msg){ - r.Format("channel: %s\nmessage: %s\n", - msg.GetChannel(), msg.GetMessage()); + r.Fmt(FMT_STRING("channel: {}\nmessage: {}\n"), + msg.GetChannel(), msg.GetMessage()); }); return CommandResult::OK; diff --git a/src/command/NeighborCommands.cxx b/src/command/NeighborCommands.cxx index b2e7ed51f..f67bb1a11 100644 --- a/src/command/NeighborCommands.cxx +++ b/src/command/NeighborCommands.cxx @@ -25,6 +25,8 @@ #include "neighbor/Glue.hxx" #include "neighbor/Info.hxx" +#include + #include bool @@ -44,9 +46,9 @@ handle_listneighbors(Client &client, [[maybe_unused]] Request args, Response &r) } for (const auto &i : neighbors->GetList()) - r.Format("neighbor: %s\n" - "name: %s\n", - i.uri.c_str(), - i.display_name.c_str()); + r.Fmt(FMT_STRING("neighbor: {}\n" + "name: {}\n"), + i.uri, + i.display_name); return CommandResult::OK; } diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx index e4fa77a6e..f3121c693 100644 --- a/src/command/OtherCommands.cxx +++ b/src/command/OtherCommands.cxx @@ -55,13 +55,15 @@ #include "db/update/Service.hxx" #endif +#include + #include static void print_spl_list(Response &r, const PlaylistVector &list) { for (const auto &i : list) { - r.Format("playlist: %s\n", i.name.c_str()); + r.Fmt(FMT_STRING("playlist: {}\n"), i.name); if (!IsNegative(i.mtime)) time_print(r, "Last-Modified", i.mtime); @@ -72,7 +74,7 @@ CommandResult handle_urlhandlers(Client &client, [[maybe_unused]] Request args, Response &r) { if (client.IsLocal()) - r.Format("handler: file://\n"); + r.Write("handler: file://\n"); print_supported_uri_schemes(r); return CommandResult::OK; } @@ -248,7 +250,7 @@ handle_update(Response &r, UpdateService &update, const char *uri_utf8, bool discard) { unsigned ret = update.Enqueue(uri_utf8, discard); - r.Format("updating_db: %i\n", ret); + r.Fmt(FMT_STRING("updating_db: {}\n"), ret); return CommandResult::OK; } @@ -258,7 +260,7 @@ handle_update(Response &r, Database &db, { unsigned id = db.Update(uri_utf8, discard); if (id > 0) { - r.Format("updating_db: %i\n", id); + r.Fmt(FMT_STRING("updating_db: {}\n"), id); return CommandResult::OK; } else { /* Database::Update() has returned 0 without setting @@ -325,7 +327,7 @@ handle_getvol(Client &client, Request, Response &r) const auto volume = volume_level_get(partition.outputs); if (volume >= 0) - r.Format("volume: %i\n", volume); + r.Fmt(FMT_STRING("volume: {}\n"), volume); return CommandResult::OK; } @@ -391,7 +393,7 @@ handle_config(Client &client, [[maybe_unused]] Request args, Response &r) const Storage *storage = client.GetStorage(); if (storage != nullptr) { const auto path = storage->MapUTF8(""); - r.Format("music_directory: %s\n", path.c_str()); + r.Fmt(FMT_STRING("music_directory: {}\n"), path); } #endif diff --git a/src/command/PartitionCommands.cxx b/src/command/PartitionCommands.cxx index 2a65cfd09..2d221feab 100644 --- a/src/command/PartitionCommands.cxx +++ b/src/command/PartitionCommands.cxx @@ -27,6 +27,8 @@ #include "client/Response.hxx" #include "util/CharUtil.hxx" +#include + CommandResult handle_partition(Client &client, Request request, Response &response) { @@ -46,7 +48,7 @@ CommandResult handle_listpartitions(Client &client, Request, Response &r) { for (const auto &partition : client.GetInstance().partitions) { - r.Format("partition: %s\n", partition.name.c_str()); + r.Fmt(FMT_STRING("partition: {}\n"), partition.name); } return CommandResult::OK; diff --git a/src/command/PlayerCommands.cxx b/src/command/PlayerCommands.cxx index cfd64ba72..3bc867f1c 100644 --- a/src/command/PlayerCommands.cxx +++ b/src/command/PlayerCommands.cxx @@ -38,6 +38,8 @@ #include "db/update/Service.hxx" #endif +#include + #define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_REPEAT "repeat" #define COMMAND_STATUS_SINGLE "single" @@ -131,60 +133,60 @@ handle_status(Client &client, [[maybe_unused]] Request args, Response &r) const auto volume = volume_level_get(partition.outputs); if (volume >= 0) - r.Format("volume: %i\n", volume); + r.Fmt(FMT_STRING("volume: {}\n"), volume); - r.Format(COMMAND_STATUS_REPEAT ": %i\n" - COMMAND_STATUS_RANDOM ": %i\n" - COMMAND_STATUS_SINGLE ": %s\n" - COMMAND_STATUS_CONSUME ": %i\n" - "partition: %s\n" - COMMAND_STATUS_PLAYLIST ": %li\n" - COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n" - COMMAND_STATUS_MIXRAMPDB ": %f\n" - COMMAND_STATUS_STATE ": %s\n", - playlist.GetRepeat(), - playlist.GetRandom(), - SingleToString(playlist.GetSingle()), - playlist.GetConsume(), - partition.name.c_str(), - (unsigned long)playlist.GetVersion(), - playlist.GetLength(), - (double)pc.GetMixRampDb(), - state); + r.Fmt(FMT_STRING(COMMAND_STATUS_REPEAT ": {}\n" + COMMAND_STATUS_RANDOM ": {}\n" + COMMAND_STATUS_SINGLE ": {}\n" + COMMAND_STATUS_CONSUME ": {}\n" + "partition: {}\n" + COMMAND_STATUS_PLAYLIST ": {}\n" + COMMAND_STATUS_PLAYLIST_LENGTH ": {}\n" + COMMAND_STATUS_MIXRAMPDB ": {}\n" + COMMAND_STATUS_STATE ": {}\n"), + playlist.GetRepeat(), + playlist.GetRandom(), + SingleToString(playlist.GetSingle()), + playlist.GetConsume(), + partition.name.c_str(), + playlist.GetVersion(), + playlist.GetLength(), + pc.GetMixRampDb(), + state); if (pc.GetCrossFade() > FloatDuration::zero()) - r.Format(COMMAND_STATUS_CROSSFADE ": %lu\n", - lround(pc.GetCrossFade().count())); + r.Fmt(FMT_STRING(COMMAND_STATUS_CROSSFADE ": {}\n"), + lround(pc.GetCrossFade().count())); if (pc.GetMixRampDelay() > FloatDuration::zero()) - r.Format(COMMAND_STATUS_MIXRAMPDELAY ": %f\n", - pc.GetMixRampDelay().count()); + r.Fmt(FMT_STRING(COMMAND_STATUS_MIXRAMPDELAY ": {}\n"), + pc.GetMixRampDelay().count()); song = playlist.GetCurrentPosition(); if (song >= 0) { - r.Format(COMMAND_STATUS_SONG ": %i\n" - COMMAND_STATUS_SONGID ": %u\n", - song, playlist.PositionToId(song)); + r.Fmt(FMT_STRING(COMMAND_STATUS_SONG ": {}\n" + COMMAND_STATUS_SONGID ": {}\n"), + song, playlist.PositionToId(song)); } if (player_status.state != PlayerState::STOP) { - r.Format(COMMAND_STATUS_TIME ": %i:%i\n" - "elapsed: %1.3f\n" - COMMAND_STATUS_BITRATE ": %u\n", - player_status.elapsed_time.RoundS(), - player_status.total_time.IsNegative() - ? 0U - : unsigned(player_status.total_time.RoundS()), - player_status.elapsed_time.ToDoubleS(), - player_status.bit_rate); + r.Fmt(FMT_STRING(COMMAND_STATUS_TIME ": {}:{}\n" + "elapsed: {:1.3}\n" + COMMAND_STATUS_BITRATE ": {}\n"), + player_status.elapsed_time.RoundS(), + player_status.total_time.IsNegative() + ? 0U + : unsigned(player_status.total_time.RoundS()), + player_status.elapsed_time.ToDoubleS(), + player_status.bit_rate); if (!player_status.total_time.IsNegative()) - r.Format("duration: %1.3f\n", + r.Fmt(FMT_STRING("duration: {:1.3}\n"), player_status.total_time.ToDoubleS()); if (player_status.audio_format.IsDefined()) - r.Format(COMMAND_STATUS_AUDIO ": %s\n", - ToString(player_status.audio_format).c_str()); + r.Fmt(FMT_STRING(COMMAND_STATUS_AUDIO ": {}\n"), + ToString(player_status.audio_format)); } #ifdef ENABLE_DATABASE @@ -193,23 +195,23 @@ handle_status(Client &client, [[maybe_unused]] Request args, Response &r) ? update_service->GetId() : 0; if (updateJobId != 0) { - r.Format(COMMAND_STATUS_UPDATING_DB ": %i\n", - updateJobId); + r.Fmt(FMT_STRING(COMMAND_STATUS_UPDATING_DB ": {}\n"), + updateJobId); } #endif try { pc.LockCheckRethrowError(); } catch (...) { - r.Format(COMMAND_STATUS_ERROR ": %s\n", - GetFullMessage(std::current_exception()).c_str()); + r.Fmt(FMT_STRING(COMMAND_STATUS_ERROR ": {}\n"), + GetFullMessage(std::current_exception())); } song = playlist.GetNextPosition(); if (song >= 0) - r.Format(COMMAND_STATUS_NEXTSONG ": %i\n" - COMMAND_STATUS_NEXTSONGID ": %u\n", - song, playlist.PositionToId(song)); + r.Fmt(FMT_STRING(COMMAND_STATUS_NEXTSONG ": {}\n" + COMMAND_STATUS_NEXTSONGID ": {}\n"), + song, playlist.PositionToId(song)); return CommandResult::OK; } @@ -351,7 +353,7 @@ CommandResult handle_replay_gain_status(Client &client, [[maybe_unused]] Request args, Response &r) { - r.Format("replay_gain_mode: %s\n", - ToString(client.GetPartition().replay_gain_mode)); + r.Fmt(FMT_STRING("replay_gain_mode: {}\n"), + ToString(client.GetPartition().replay_gain_mode)); return CommandResult::OK; } diff --git a/src/command/PlaylistCommands.cxx b/src/command/PlaylistCommands.cxx index 5670f401e..97ed475dc 100644 --- a/src/command/PlaylistCommands.cxx +++ b/src/command/PlaylistCommands.cxx @@ -42,6 +42,8 @@ #include "util/UriExtract.hxx" #include "LocateUri.hxx" +#include + bool playlist_commands_available() noexcept { @@ -52,7 +54,7 @@ static void print_spl_list(Response &r, const PlaylistVector &list) { for (const auto &i : list) { - r.Format("playlist: %s\n", i.name.c_str()); + r.Fmt(FMT_STRING("playlist: {}\n"), i.name); if (!IsNegative(i.mtime)) time_print(r, "Last-Modified", i.mtime); diff --git a/src/command/QueueCommands.cxx b/src/command/QueueCommands.cxx index c0161779e..7844aacaf 100644 --- a/src/command/QueueCommands.cxx +++ b/src/command/QueueCommands.cxx @@ -39,6 +39,8 @@ #include "util/StringAPI.hxx" #include "util/NumberParser.hxx" +#include + #include static void @@ -127,7 +129,7 @@ handle_addid(Client &client, Request args, Response &r) } } - r.Format("Id: %u\n", added_id); + r.Fmt(FMT_STRING("Id: {}\n"), added_id); return CommandResult::OK; } diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx index 7fd6fc75f..b547a2da6 100644 --- a/src/command/StorageCommands.cxx +++ b/src/command/StorageCommands.cxx @@ -17,8 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define __STDC_FORMAT_MACROS /* for PRIu64 */ - #include "config.h" #include "StorageCommands.hxx" #include "Request.hxx" @@ -37,7 +35,8 @@ #include "TimePrint.hxx" #include "IdleFlags.hxx" -#include /* for PRIu64 */ +#include + #include gcc_pure @@ -47,13 +46,6 @@ skip_path(const char *name_utf8) noexcept return std::strchr(name_utf8, '\n') != nullptr; } -#if defined(_WIN32) && GCC_CHECK_VERSION(4,6) -/* PRIu64 causes bogus compiler warning */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat" -#pragma GCC diagnostic ignored "-Wformat-extra-args" -#endif - static void handle_listfiles_storage(Response &r, StorageDirectoryReader &reader) { @@ -75,14 +67,14 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader) continue; case StorageFileInfo::Type::REGULAR: - r.Format("file: %s\n" - "size: %" PRIu64 "\n", - name_utf8, - info.size); + r.Fmt(FMT_STRING("file: {}\n" + "size: {}\n"), + name_utf8, + info.size); break; case StorageFileInfo::Type::DIRECTORY: - r.Format("directory: %s\n", name_utf8); + r.Fmt(FMT_STRING("directory: {}\n"), name_utf8); break; } @@ -139,7 +131,7 @@ print_storage_uri(Client &client, Response &r, const Storage &storage) uri = std::move(allocated); } - r.Format("storage: %s\n", uri.c_str()); + r.Fmt(FMT_STRING("storage: {}\n"), uri); } CommandResult @@ -155,7 +147,7 @@ handle_listmounts(Client &client, [[maybe_unused]] Request args, Response &r) const auto visitor = [&client, &r](const char *mount_uri, const Storage &storage){ - r.Format("mount: %s\n", mount_uri); + r.Fmt(FMT_STRING("mount: {}\n"), mount_uri); print_storage_uri(client, r, storage); }; diff --git a/src/db/Count.cxx b/src/db/Count.cxx index 695991c5b..6925440b5 100644 --- a/src/db/Count.cxx +++ b/src/db/Count.cxx @@ -27,6 +27,8 @@ #include "tag/VisitFallback.hxx" #include "TagPrint.hxx" +#include + #include #include @@ -47,9 +49,9 @@ PrintSearchStats(Response &r, const SearchStats &stats) noexcept unsigned total_duration_s = std::chrono::duration_cast(stats.total_duration).count(); - r.Format("songs: %u\n" - "playtime: %u\n", - stats.n_songs, total_duration_s); + r.Fmt(FMT_STRING("songs: {}\n" + "playtime: {}\n"), + stats.n_songs, total_duration_s); } static void diff --git a/src/db/DatabasePrint.cxx b/src/db/DatabasePrint.cxx index 46732b3b6..516a92f54 100644 --- a/src/db/DatabasePrint.cxx +++ b/src/db/DatabasePrint.cxx @@ -32,6 +32,8 @@ #include "time/ChronoUtil.hxx" #include "util/RecursiveMap.hxx" +#include + #include gcc_pure @@ -47,8 +49,8 @@ static void PrintDirectoryURI(Response &r, bool base, const LightDirectory &directory) noexcept { - r.Format("directory: %s\n", - ApplyBaseFlag(directory.GetPath(), base)); + r.Fmt(FMT_STRING("directory: {}\n"), + ApplyBaseFlag(directory.GetPath(), base)); } static void @@ -77,11 +79,11 @@ print_playlist_in_directory(Response &r, bool base, const char *name_utf8) noexcept { if (base || directory == nullptr) - r.Format("playlist: %s\n", - ApplyBaseFlag(name_utf8, base)); + r.Fmt(FMT_STRING("playlist: {}\n"), + ApplyBaseFlag(name_utf8, base)); else - r.Format("playlist: %s/%s\n", - directory, name_utf8); + r.Fmt(FMT_STRING("playlist: {}/{}\n"), + directory, name_utf8); } static void @@ -90,10 +92,10 @@ print_playlist_in_directory(Response &r, bool base, const char *name_utf8) noexcept { if (base || directory == nullptr || directory->IsRoot()) - r.Format("playlist: %s\n", name_utf8); + r.Fmt(FMT_STRING("playlist: {}\n"), name_utf8); else - r.Format("playlist: %s/%s\n", - directory->GetPath(), name_utf8); + r.Fmt(FMT_STRING("playlist: {}/{}\n"), + directory->GetPath(), name_utf8); } static void @@ -196,7 +198,7 @@ PrintUniqueTags(Response &r, ConstBuffer tag_types, tag_types.pop_front(); for (const auto &[key, tag] : map) { - r.Format("%s: %s\n", name, key.c_str()); + r.Fmt(FMT_STRING("{}: {}\n"), name, key); if (!tag_types.empty()) PrintUniqueTags(r, tag_types, tag); diff --git a/src/db/meson.build b/src/db/meson.build index 69bf50cd6..694bd5204 100644 --- a/src/db/meson.build +++ b/src/db/meson.build @@ -55,6 +55,7 @@ db_glue = static_library( include_directories: inc, dependencies: [ boost_dep, + fmt_dep, log_dep, ], ) diff --git a/src/decoder/DecoderPrint.cxx b/src/decoder/DecoderPrint.cxx index 351206c73..61bc9cd45 100644 --- a/src/decoder/DecoderPrint.cxx +++ b/src/decoder/DecoderPrint.cxx @@ -22,6 +22,8 @@ #include "DecoderPlugin.hxx" #include "client/Response.hxx" +#include + #include #include @@ -33,15 +35,15 @@ decoder_plugin_print(Response &r, assert(plugin.name != nullptr); - r.Format("plugin: %s\n", plugin.name); + r.Fmt(FMT_STRING("plugin: {}\n"), plugin.name); if (plugin.suffixes != nullptr) for (p = plugin.suffixes; *p != nullptr; ++p) - r.Format("suffix: %s\n", *p); + r.Fmt(FMT_STRING("suffix: {}\n"), *p); if (plugin.mime_types != nullptr) for (p = plugin.mime_types; *p != nullptr; ++p) - r.Format("mime_type: %s\n", *p); + r.Fmt(FMT_STRING("mime_type: {}\n"), *p); } void diff --git a/src/ls.cxx b/src/ls.cxx index 814835fc3..ce34b24ba 100644 --- a/src/ls.cxx +++ b/src/ls.cxx @@ -26,8 +26,9 @@ #include "client/Response.hxx" #include "util/UriExtract.hxx" -#include +#include +#include #include void print_supported_uri_schemes_to_fp(FILE *fp) @@ -67,7 +68,7 @@ print_supported_uri_schemes(Response &r) }); for (const auto& protocol : protocols) { - r.Format("handler: %s\n", protocol.c_str()); + r.Fmt(FMT_STRING("handler: {}\n"), protocol); } } diff --git a/src/output/Print.cxx b/src/output/Print.cxx index 9f8edf193..cd59b91df 100644 --- a/src/output/Print.cxx +++ b/src/output/Print.cxx @@ -26,21 +26,24 @@ #include "MultipleOutputs.hxx" #include "client/Response.hxx" +#include + void printAudioDevices(Response &r, const MultipleOutputs &outputs) { for (unsigned i = 0, n = outputs.Size(); i != n; ++i) { const auto &ao = outputs.Get(i); - r.Format("outputid: %u\n" - "outputname: %s\n" - "plugin: %s\n" - "outputenabled: %i\n", - i, - ao.GetName(), ao.GetPluginName(), - ao.IsEnabled()); + r.Fmt(FMT_STRING("outputid: {}\n" + "outputname: {}\n" + "plugin: {}\n" + "outputenabled: {}\n"), + i, + ao.GetName(), ao.GetPluginName(), + ao.IsEnabled()); for (const auto &[attribute, value] : ao.GetAttributes()) - r.Format("attribute: %s=%s\n", attribute.c_str(), value.c_str()); + r.Fmt(FMT_STRING("attribute: {}={}\n"), + attribute, value); } } diff --git a/src/output/meson.build b/src/output/meson.build index c4384e716..eba248625 100644 --- a/src/output/meson.build +++ b/src/output/meson.build @@ -35,6 +35,9 @@ output_glue = static_library( 'Finish.cxx', 'Init.cxx', include_directories: inc, + dependencies: [ + fmt_dep, + ], ) output_glue_dep = declare_dependency( diff --git a/src/queue/QueuePrint.cxx b/src/queue/QueuePrint.cxx index 3f24de785..f11d4b8d8 100644 --- a/src/queue/QueuePrint.cxx +++ b/src/queue/QueuePrint.cxx @@ -25,6 +25,8 @@ #include "song/LightSong.hxx" #include "client/Response.hxx" +#include + /** * Send detailed information about a range of songs in the queue to a * client. @@ -38,12 +40,12 @@ queue_print_song_info(Response &r, const Queue &queue, unsigned position) { song_print_info(r, queue.Get(position)); - r.Format("Pos: %u\nId: %u\n", - position, queue.PositionToId(position)); + r.Fmt(FMT_STRING("Pos: {}\nId: {}\n"), + position, queue.PositionToId(position)); uint8_t priority = queue.GetPriorityAtPosition(position); if (priority != 0) - r.Format("Prio: %u\n", priority); + r.Fmt(FMT_STRING("Prio: {}\n"), priority); } void @@ -65,7 +67,7 @@ queue_print_uris(Response &r, const Queue &queue, assert(end <= queue.GetLength()); for (unsigned i = start; i < end; ++i) { - r.Format("%i:", i); + r.Fmt(FMT_STRING("{}:"), i); song_print_uri(r, queue.Get(i)); } } @@ -93,8 +95,8 @@ queue_print_changes_position(Response &r, const Queue &queue, for (unsigned i = start; i < end; i++) if (queue.IsNewerAtPosition(i, version)) - r.Format("cpos: %i\nId: %i\n", - i, queue.PositionToId(i)); + r.Fmt(FMT_STRING("cpos: {}\nId: {}\n"), + i, queue.PositionToId(i)); } void diff --git a/src/sticker/Print.cxx b/src/sticker/Print.cxx index b60325b3c..fc9c3fee1 100644 --- a/src/sticker/Print.cxx +++ b/src/sticker/Print.cxx @@ -21,11 +21,13 @@ #include "Sticker.hxx" #include "client/Response.hxx" +#include + void sticker_print_value(Response &r, const char *name, const char *value) { - r.Format("sticker: %s=%s\n", name, value); + r.Fmt(FMT_STRING("sticker: {}={}\n"), name, value); } void