Commit 0440c41c authored by Max Kellermann's avatar Max Kellermann

client/Response: add method Fmt() based on libfmt

parent a9c704b7
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "time/ChronoUtil.hxx" #include "time/ChronoUtil.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include <fmt/format.h>
#define SONG_FILE "file: " #define SONG_FILE "file: "
static void static void
...@@ -42,14 +44,15 @@ song_print_uri(Response &r, const char *uri, bool base) noexcept ...@@ -42,14 +44,15 @@ song_print_uri(Response &r, const char *uri, bool base) noexcept
uri = allocated.c_str(); uri = allocated.c_str();
} }
r.Format(SONG_FILE "%s\n", uri); r.Fmt(FMT_STRING(SONG_FILE "{}\n"), uri);
} }
void void
song_print_uri(Response &r, const LightSong &song, bool base) noexcept song_print_uri(Response &r, const LightSong &song, bool base) noexcept
{ {
if (!base && song.directory != nullptr) 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 else
song_print_uri(r, song.uri, base); song_print_uri(r, song.uri, base);
} }
...@@ -67,15 +70,15 @@ PrintRange(Response &r, SongTime start_time, SongTime end_time) noexcept ...@@ -67,15 +70,15 @@ PrintRange(Response &r, SongTime start_time, SongTime end_time) noexcept
const unsigned end_ms = end_time.ToMS(); const unsigned end_ms = end_time.ToMS();
if (end_ms > 0) if (end_ms > 0)
r.Format("Range: %u.%03u-%u.%03u\n", r.Fmt(FMT_STRING("Range: {}.{:03}-{}.{:03}\n"),
start_ms / 1000, start_ms / 1000,
start_ms % 1000, start_ms % 1000,
end_ms / 1000, end_ms / 1000,
end_ms % 1000); end_ms % 1000);
else if (start_ms > 0) else if (start_ms > 0)
r.Format("Range: %u.%03u-\n", r.Fmt(FMT_STRING("Range: {}.{:03}-\n"),
start_ms / 1000, start_ms / 1000,
start_ms % 1000); start_ms % 1000);
} }
void void
...@@ -89,16 +92,16 @@ song_print_info(Response &r, const LightSong &song, bool base) noexcept ...@@ -89,16 +92,16 @@ song_print_info(Response &r, const LightSong &song, bool base) noexcept
time_print(r, "Last-Modified", song.mtime); time_print(r, "Last-Modified", song.mtime);
if (song.audio_format.IsDefined()) 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); tag_print_values(r, song.tag);
const auto duration = song.GetDuration(); const auto duration = song.GetDuration();
if (!duration.IsNegative()) if (!duration.IsNegative())
r.Format("Time: %i\n" r.Fmt(FMT_STRING("Time: {}\n"
"duration: %1.3f\n", "duration: {:1.3}\n"),
duration.RoundS(), duration.RoundS(),
duration.ToDoubleS()); duration.ToDoubleS());
} }
void void
...@@ -112,14 +115,14 @@ song_print_info(Response &r, const DetachedSong &song, bool base) noexcept ...@@ -112,14 +115,14 @@ song_print_info(Response &r, const DetachedSong &song, bool base) noexcept
time_print(r, "Last-Modified", song.GetLastModified()); time_print(r, "Last-Modified", song.GetLastModified());
if (const auto &f = song.GetAudioFormat(); f.IsDefined()) 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()); tag_print_values(r, song.GetTag());
const auto duration = song.GetDuration(); const auto duration = song.GetDuration();
if (!duration.IsNegative()) if (!duration.IsNegative())
r.Format("Time: %i\n" r.Fmt(FMT_STRING("Time: {}\n"
"duration: %1.3f\n", "duration: {:1.3}\n"),
duration.RoundS(), duration.RoundS(),
duration.ToDoubleS()); duration.ToDoubleS());
} }
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include "system/Clock.hxx" #include "system/Clock.hxx"
#endif #endif
#include <fmt/format.h>
#include <chrono> #include <chrono>
#ifndef _WIN32 #ifndef _WIN32
...@@ -97,19 +99,19 @@ db_stats_print(Response &r, const Database &db) ...@@ -97,19 +99,19 @@ db_stats_print(Response &r, const Database &db)
unsigned total_duration_s = unsigned total_duration_s =
std::chrono::duration_cast<std::chrono::seconds>(stats.total_duration).count(); std::chrono::duration_cast<std::chrono::seconds>(stats.total_duration).count();
r.Format("artists: %u\n" r.Fmt(FMT_STRING("artists: {}\n"
"albums: %u\n" "albums: {}\n"
"songs: %u\n" "songs: {}\n"
"db_playtime: %u\n", "db_playtime: {}\n"),
stats.artist_count, stats.artist_count,
stats.album_count, stats.album_count,
stats.song_count, stats.song_count,
total_duration_s); total_duration_s);
const auto update_stamp = db.GetUpdateStamp(); const auto update_stamp = db.GetUpdateStamp();
if (!IsNegative(update_stamp)) if (!IsNegative(update_stamp))
r.Format("db_update: %lu\n", r.Fmt(FMT_STRING("db_update: {}\n"),
(unsigned long)std::chrono::system_clock::to_time_t(update_stamp)); std::chrono::system_clock::to_time_t(update_stamp));
} }
#endif #endif
...@@ -123,10 +125,10 @@ stats_print(Response &r, const Partition &partition) ...@@ -123,10 +125,10 @@ stats_print(Response &r, const Partition &partition)
const auto uptime = std::chrono::steady_clock::now() - start_time; const auto uptime = std::chrono::steady_clock::now() - start_time;
#endif #endif
r.Format("uptime: %u\n" r.Fmt(FMT_STRING("uptime: {}\n"
"playtime: %lu\n", "playtime: {}\n"),
(unsigned)std::chrono::duration_cast<std::chrono::seconds>(uptime).count(), std::chrono::duration_cast<std::chrono::seconds>(uptime).count(),
lround(partition.pc.GetTotalPlayTime().count())); lround(partition.pc.GetTotalPlayTime().count()));
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const Database *db = partition.instance.GetDatabase(); const Database *db = partition.instance.GetDatabase();
......
...@@ -23,26 +23,27 @@ ...@@ -23,26 +23,27 @@
#include "client/Response.hxx" #include "client/Response.hxx"
#include "util/StringView.hxx" #include "util/StringView.hxx"
#include <fmt/format.h>
void void
tag_print_types(Response &r) noexcept tag_print_types(Response &r) noexcept
{ {
const auto tag_mask = global_tag_mask & r.GetTagMask(); const auto tag_mask = global_tag_mask & r.GetTagMask();
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++)
if (tag_mask.Test(TagType(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 void
tag_print(Response &r, TagType type, StringView value) noexcept tag_print(Response &r, TagType type, StringView value) noexcept
{ {
r.Format("%s: %.*s\n", tag_item_names[type], r.Fmt(FMT_STRING("{}: {}\n"), tag_item_names[type], value);
int(value.size), value.data);
} }
void void
tag_print(Response &r, TagType type, const char *value) noexcept 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 void
...@@ -58,10 +59,10 @@ void ...@@ -58,10 +59,10 @@ void
tag_print(Response &r, const Tag &tag) noexcept tag_print(Response &r, const Tag &tag) noexcept
{ {
if (!tag.duration.IsNegative()) if (!tag.duration.IsNegative())
r.Format("Time: %i\n" r.Fmt(FMT_STRING("Time: {}\n"
"duration: %1.3f\n", "duration: {:1.3}\n"),
tag.duration.RoundS(), tag.duration.RoundS(),
tag.duration.ToDoubleS()); tag.duration.ToDoubleS());
tag_print_values(r, tag); tag_print_values(r, tag);
} }
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "client/Response.hxx" #include "client/Response.hxx"
#include "time/ISO8601.hxx" #include "time/ISO8601.hxx"
#include <fmt/format.h>
void void
time_print(Response &r, const char *name, time_print(Response &r, const char *name,
std::chrono::system_clock::time_point t) std::chrono::system_clock::time_point t)
...@@ -33,5 +35,5 @@ time_print(Response &r, const char *name, ...@@ -33,5 +35,5 @@ time_print(Response &r, const char *name,
return; return;
} }
r.Format("%s: %s\n", name, s.c_str()); r.Fmt(FMT_STRING("{}: {}\n"), name, s);
} }
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "Response.hxx" #include "Response.hxx"
#include "Idle.hxx" #include "Idle.hxx"
#include <fmt/format.h>
#include <cassert> #include <cassert>
static void static void
...@@ -30,7 +32,7 @@ WriteIdleResponse(Response &r, unsigned flags) noexcept ...@@ -30,7 +32,7 @@ WriteIdleResponse(Response &r, unsigned flags) noexcept
const char *const*idle_names = idle_get_names(); const char *const*idle_names = idle_get_names();
for (unsigned i = 0; idle_names[i]; ++i) { for (unsigned i = 0; idle_names[i]; ++i) {
if (flags & (1 << 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"); r.Write("OK\n");
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "util/FormatString.hxx" #include "util/FormatString.hxx"
#include "util/AllocatedString.hxx" #include "util/AllocatedString.hxx"
#include <fmt/format.h>
TagMask TagMask
Response::GetTagMask() const noexcept Response::GetTagMask() const noexcept
{ {
...@@ -57,16 +59,20 @@ Response::Format(const char *fmt, ...) noexcept ...@@ -57,16 +59,20 @@ Response::Format(const char *fmt, ...) noexcept
} }
bool 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<void> payload) noexcept Response::WriteBinary(ConstBuffer<void> payload) noexcept
{ {
assert(payload.size <= client.binary_limit); assert(payload.size <= client.binary_limit);
return return
#ifdef _WIN32 Fmt("binary: {}\n", payload.size) &&
Format("binary: %lu\n", (unsigned long)payload.size) &&
#else
Format("binary: %zu\n", payload.size) &&
#endif
Write(payload.data, payload.size) && Write(payload.data, payload.size) &&
Write("\n"); Write("\n");
} }
......
...@@ -23,6 +23,11 @@ ...@@ -23,6 +23,11 @@
#include "protocol/Ack.hxx" #include "protocol/Ack.hxx"
#include "util/Compiler.h" #include "util/Compiler.h"
#include <fmt/core.h>
#if FMT_VERSION < 70000
#include <fmt/format.h>
#endif
#include <cstdarg> #include <cstdarg>
#include <cstddef> #include <cstddef>
...@@ -79,6 +84,21 @@ public: ...@@ -79,6 +84,21 @@ public:
gcc_printf(2,3) gcc_printf(2,3)
bool Format(const char *fmt, ...) noexcept; bool Format(const char *fmt, ...) noexcept;
bool VFmt(fmt::string_view format_str, fmt::format_args args) noexcept;
template<typename S, typename... Args>
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<Args...>(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 * Write a binary chunk; this writes the "binary" line, the
* given chunk and the trailing newline. * given chunk and the trailing newline.
......
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
#include "StickerCommands.hxx" #include "StickerCommands.hxx"
#endif #endif
#include <fmt/format.h>
#include <cassert> #include <cassert>
#include <iterator> #include <iterator>
...@@ -253,7 +255,7 @@ PrintAvailableCommands(Response &r, const Partition &partition, ...@@ -253,7 +255,7 @@ PrintAvailableCommands(Response &r, const Partition &partition,
if (cmd->permission == (permission & cmd->permission) && if (cmd->permission == (permission & cmd->permission) &&
command_available(partition, cmd)) command_available(partition, cmd))
r.Format("command: %s\n", cmd->cmd); r.Fmt(FMT_STRING("command: {}\n"), cmd->cmd);
} }
return CommandResult::OK; return CommandResult::OK;
...@@ -266,7 +268,7 @@ PrintUnavailableCommands(Response &r, unsigned permission) noexcept ...@@ -266,7 +268,7 @@ PrintUnavailableCommands(Response &r, unsigned permission) noexcept
const struct command *cmd = &i; const struct command *cmd = &i;
if (cmd->permission != (permission & cmd->permission)) if (cmd->permission != (permission & cmd->permission))
r.Format("command: %s\n", cmd->cmd); r.Fmt(FMT_STRING("command: {}\n"), cmd->cmd);
} }
return CommandResult::OK; return CommandResult::OK;
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#define __STDC_FORMAT_MACROS /* for PRIu64 */
#include "config.h" #include "config.h"
#include "FileCommands.hxx" #include "FileCommands.hxx"
#include "Request.hxx" #include "Request.hxx"
...@@ -43,9 +41,10 @@ ...@@ -43,9 +41,10 @@
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <fmt/format.h>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cinttypes> /* for PRIu64 */
gcc_pure gcc_pure
static bool static bool
...@@ -61,13 +60,6 @@ skip_path(Path name_fs) noexcept ...@@ -61,13 +60,6 @@ skip_path(Path name_fs) noexcept
return name_fs.HasNewline(); 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 CommandResult
handle_listfiles_local(Response &r, Path path_fs) handle_listfiles_local(Response &r, Path path_fs)
{ {
...@@ -88,12 +80,12 @@ handle_listfiles_local(Response &r, Path path_fs) ...@@ -88,12 +80,12 @@ handle_listfiles_local(Response &r, Path path_fs)
continue; continue;
if (fi.IsRegular()) if (fi.IsRegular())
r.Format("file: %s\n" r.Fmt(FMT_STRING("file: {}\n"
"size: %" PRIu64 "\n", "size: {}\n"),
name_utf8.c_str(), name_utf8,
fi.GetSize()); fi.GetSize());
else if (fi.IsDirectory()) else if (fi.IsDirectory())
r.Format("directory: %s\n", name_utf8.c_str()); r.Fmt(FMT_STRING("directory: {}\n"), name_utf8);
else else
continue; continue;
...@@ -135,9 +127,7 @@ public: ...@@ -135,9 +127,7 @@ public:
void OnPair(StringView key, StringView value) noexcept override { void OnPair(StringView key, StringView value) noexcept override {
if (IsValidName(key) && IsValidValue(value)) if (IsValidName(key) && IsValidValue(value))
response.Format("%.*s: %.*s\n", response.Fmt(FMT_STRING("{}: {}\n"), key, value);
int(key.size), key.data,
int(value.size), value.data);
} }
}; };
...@@ -228,11 +218,7 @@ read_stream_art(Response &r, const char *uri, size_t offset) ...@@ -228,11 +218,7 @@ read_stream_art(Response &r, const char *uri, size_t offset)
read_size = is->Read(lock, buffer.get(), buffer_size); read_size = is->Read(lock, buffer.get(), buffer_size);
} }
#ifdef _WIN32 r.Fmt(FMT_STRING("size: {}\n"), art_file_size);
r.Format("size: %lu\n", (unsigned long)art_file_size);
#else
r.Format("size: %" PRIoffset "\n", art_file_size);
#endif
r.WriteBinary({buffer.get(), read_size}); r.WriteBinary({buffer.get(), read_size});
...@@ -315,14 +301,10 @@ public: ...@@ -315,14 +301,10 @@ public:
return; return;
} }
#ifdef _WIN32 response.Fmt(FMT_STRING("size: {}\n"), buffer.size);
response.Format("size: %lu\n", (unsigned long)buffer.size);
#else
response.Format("size: %zu\n", buffer.size);
#endif
if (mime_type != nullptr) if (mime_type != nullptr)
response.Format("type: %s\n", mime_type); response.Fmt(FMT_STRING("type: {}\n"), mime_type);
buffer.size -= offset; buffer.size -= offset;
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "util/MimeType.hxx" #include "util/MimeType.hxx"
#include "util/UriExtract.hxx" #include "util/UriExtract.hxx"
#include <fmt/format.h>
class GetChromaprintCommand final class GetChromaprintCommand final
: public ThreadBackgroundCommand, ChromaprintDecoderClient, InputStreamHandler : public ThreadBackgroundCommand, ChromaprintDecoderClient, InputStreamHandler
{ {
...@@ -60,8 +62,8 @@ protected: ...@@ -60,8 +62,8 @@ protected:
void Run() override; void Run() override;
void SendResponse(Response &r) noexcept override { void SendResponse(Response &r) noexcept override {
r.Format("chromaprint: %s\n", r.Fmt(FMT_STRING("chromaprint: {}\n"),
GetFingerprint().c_str()); GetFingerprint());
} }
void CancelThread() noexcept override { void CancelThread() noexcept override {
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#include "Partition.hxx" #include "Partition.hxx"
#include <fmt/format.h>
#include <cassert> #include <cassert>
#include <set> #include <set>
#include <string> #include <string>
...@@ -85,7 +87,7 @@ handle_channels(Client &client, [[maybe_unused]] Request args, Response &r) ...@@ -85,7 +87,7 @@ handle_channels(Client &client, [[maybe_unused]] Request args, Response &r)
} }
for (const auto &channel : channels) for (const auto &channel : channels)
r.Format("channel: %s\n", channel.c_str()); r.Fmt(FMT_STRING("channel: {}\n"), channel);
return CommandResult::OK; return CommandResult::OK;
} }
...@@ -97,8 +99,8 @@ handle_read_messages(Client &client, ...@@ -97,8 +99,8 @@ handle_read_messages(Client &client,
assert(args.empty()); assert(args.empty());
client.ConsumeMessages([&r](const auto &msg){ client.ConsumeMessages([&r](const auto &msg){
r.Format("channel: %s\nmessage: %s\n", r.Fmt(FMT_STRING("channel: {}\nmessage: {}\n"),
msg.GetChannel(), msg.GetMessage()); msg.GetChannel(), msg.GetMessage());
}); });
return CommandResult::OK; return CommandResult::OK;
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "neighbor/Glue.hxx" #include "neighbor/Glue.hxx"
#include "neighbor/Info.hxx" #include "neighbor/Info.hxx"
#include <fmt/format.h>
#include <string> #include <string>
bool bool
...@@ -44,9 +46,9 @@ handle_listneighbors(Client &client, [[maybe_unused]] Request args, Response &r) ...@@ -44,9 +46,9 @@ handle_listneighbors(Client &client, [[maybe_unused]] Request args, Response &r)
} }
for (const auto &i : neighbors->GetList()) for (const auto &i : neighbors->GetList())
r.Format("neighbor: %s\n" r.Fmt(FMT_STRING("neighbor: {}\n"
"name: %s\n", "name: {}\n"),
i.uri.c_str(), i.uri,
i.display_name.c_str()); i.display_name);
return CommandResult::OK; return CommandResult::OK;
} }
...@@ -55,13 +55,15 @@ ...@@ -55,13 +55,15 @@
#include "db/update/Service.hxx" #include "db/update/Service.hxx"
#endif #endif
#include <fmt/format.h>
#include <cassert> #include <cassert>
static void static void
print_spl_list(Response &r, const PlaylistVector &list) print_spl_list(Response &r, const PlaylistVector &list)
{ {
for (const auto &i : 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)) if (!IsNegative(i.mtime))
time_print(r, "Last-Modified", i.mtime); time_print(r, "Last-Modified", i.mtime);
...@@ -72,7 +74,7 @@ CommandResult ...@@ -72,7 +74,7 @@ CommandResult
handle_urlhandlers(Client &client, [[maybe_unused]] Request args, Response &r) handle_urlhandlers(Client &client, [[maybe_unused]] Request args, Response &r)
{ {
if (client.IsLocal()) if (client.IsLocal())
r.Format("handler: file://\n"); r.Write("handler: file://\n");
print_supported_uri_schemes(r); print_supported_uri_schemes(r);
return CommandResult::OK; return CommandResult::OK;
} }
...@@ -248,7 +250,7 @@ handle_update(Response &r, UpdateService &update, ...@@ -248,7 +250,7 @@ handle_update(Response &r, UpdateService &update,
const char *uri_utf8, bool discard) const char *uri_utf8, bool discard)
{ {
unsigned ret = update.Enqueue(uri_utf8, 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; return CommandResult::OK;
} }
...@@ -258,7 +260,7 @@ handle_update(Response &r, Database &db, ...@@ -258,7 +260,7 @@ handle_update(Response &r, Database &db,
{ {
unsigned id = db.Update(uri_utf8, discard); unsigned id = db.Update(uri_utf8, discard);
if (id > 0) { if (id > 0) {
r.Format("updating_db: %i\n", id); r.Fmt(FMT_STRING("updating_db: {}\n"), id);
return CommandResult::OK; return CommandResult::OK;
} else { } else {
/* Database::Update() has returned 0 without setting /* Database::Update() has returned 0 without setting
...@@ -325,7 +327,7 @@ handle_getvol(Client &client, Request, Response &r) ...@@ -325,7 +327,7 @@ handle_getvol(Client &client, Request, Response &r)
const auto volume = volume_level_get(partition.outputs); const auto volume = volume_level_get(partition.outputs);
if (volume >= 0) if (volume >= 0)
r.Format("volume: %i\n", volume); r.Fmt(FMT_STRING("volume: {}\n"), volume);
return CommandResult::OK; return CommandResult::OK;
} }
...@@ -391,7 +393,7 @@ handle_config(Client &client, [[maybe_unused]] Request args, Response &r) ...@@ -391,7 +393,7 @@ handle_config(Client &client, [[maybe_unused]] Request args, Response &r)
const Storage *storage = client.GetStorage(); const Storage *storage = client.GetStorage();
if (storage != nullptr) { if (storage != nullptr) {
const auto path = storage->MapUTF8(""); const auto path = storage->MapUTF8("");
r.Format("music_directory: %s\n", path.c_str()); r.Fmt(FMT_STRING("music_directory: {}\n"), path);
} }
#endif #endif
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "client/Response.hxx" #include "client/Response.hxx"
#include "util/CharUtil.hxx" #include "util/CharUtil.hxx"
#include <fmt/format.h>
CommandResult CommandResult
handle_partition(Client &client, Request request, Response &response) handle_partition(Client &client, Request request, Response &response)
{ {
...@@ -46,7 +48,7 @@ CommandResult ...@@ -46,7 +48,7 @@ CommandResult
handle_listpartitions(Client &client, Request, Response &r) handle_listpartitions(Client &client, Request, Response &r)
{ {
for (const auto &partition : client.GetInstance().partitions) { 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; return CommandResult::OK;
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include "db/update/Service.hxx" #include "db/update/Service.hxx"
#endif #endif
#include <fmt/format.h>
#define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_STATE "state"
#define COMMAND_STATUS_REPEAT "repeat" #define COMMAND_STATUS_REPEAT "repeat"
#define COMMAND_STATUS_SINGLE "single" #define COMMAND_STATUS_SINGLE "single"
...@@ -131,60 +133,60 @@ handle_status(Client &client, [[maybe_unused]] Request args, Response &r) ...@@ -131,60 +133,60 @@ handle_status(Client &client, [[maybe_unused]] Request args, Response &r)
const auto volume = volume_level_get(partition.outputs); const auto volume = volume_level_get(partition.outputs);
if (volume >= 0) if (volume >= 0)
r.Format("volume: %i\n", volume); r.Fmt(FMT_STRING("volume: {}\n"), volume);
r.Format(COMMAND_STATUS_REPEAT ": %i\n" r.Fmt(FMT_STRING(COMMAND_STATUS_REPEAT ": {}\n"
COMMAND_STATUS_RANDOM ": %i\n" COMMAND_STATUS_RANDOM ": {}\n"
COMMAND_STATUS_SINGLE ": %s\n" COMMAND_STATUS_SINGLE ": {}\n"
COMMAND_STATUS_CONSUME ": %i\n" COMMAND_STATUS_CONSUME ": {}\n"
"partition: %s\n" "partition: {}\n"
COMMAND_STATUS_PLAYLIST ": %li\n" COMMAND_STATUS_PLAYLIST ": {}\n"
COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n" COMMAND_STATUS_PLAYLIST_LENGTH ": {}\n"
COMMAND_STATUS_MIXRAMPDB ": %f\n" COMMAND_STATUS_MIXRAMPDB ": {}\n"
COMMAND_STATUS_STATE ": %s\n", COMMAND_STATUS_STATE ": {}\n"),
playlist.GetRepeat(), playlist.GetRepeat(),
playlist.GetRandom(), playlist.GetRandom(),
SingleToString(playlist.GetSingle()), SingleToString(playlist.GetSingle()),
playlist.GetConsume(), playlist.GetConsume(),
partition.name.c_str(), partition.name.c_str(),
(unsigned long)playlist.GetVersion(), playlist.GetVersion(),
playlist.GetLength(), playlist.GetLength(),
(double)pc.GetMixRampDb(), pc.GetMixRampDb(),
state); state);
if (pc.GetCrossFade() > FloatDuration::zero()) if (pc.GetCrossFade() > FloatDuration::zero())
r.Format(COMMAND_STATUS_CROSSFADE ": %lu\n", r.Fmt(FMT_STRING(COMMAND_STATUS_CROSSFADE ": {}\n"),
lround(pc.GetCrossFade().count())); lround(pc.GetCrossFade().count()));
if (pc.GetMixRampDelay() > FloatDuration::zero()) if (pc.GetMixRampDelay() > FloatDuration::zero())
r.Format(COMMAND_STATUS_MIXRAMPDELAY ": %f\n", r.Fmt(FMT_STRING(COMMAND_STATUS_MIXRAMPDELAY ": {}\n"),
pc.GetMixRampDelay().count()); pc.GetMixRampDelay().count());
song = playlist.GetCurrentPosition(); song = playlist.GetCurrentPosition();
if (song >= 0) { if (song >= 0) {
r.Format(COMMAND_STATUS_SONG ": %i\n" r.Fmt(FMT_STRING(COMMAND_STATUS_SONG ": {}\n"
COMMAND_STATUS_SONGID ": %u\n", COMMAND_STATUS_SONGID ": {}\n"),
song, playlist.PositionToId(song)); song, playlist.PositionToId(song));
} }
if (player_status.state != PlayerState::STOP) { if (player_status.state != PlayerState::STOP) {
r.Format(COMMAND_STATUS_TIME ": %i:%i\n" r.Fmt(FMT_STRING(COMMAND_STATUS_TIME ": {}:{}\n"
"elapsed: %1.3f\n" "elapsed: {:1.3}\n"
COMMAND_STATUS_BITRATE ": %u\n", COMMAND_STATUS_BITRATE ": {}\n"),
player_status.elapsed_time.RoundS(), player_status.elapsed_time.RoundS(),
player_status.total_time.IsNegative() player_status.total_time.IsNegative()
? 0U ? 0U
: unsigned(player_status.total_time.RoundS()), : unsigned(player_status.total_time.RoundS()),
player_status.elapsed_time.ToDoubleS(), player_status.elapsed_time.ToDoubleS(),
player_status.bit_rate); player_status.bit_rate);
if (!player_status.total_time.IsNegative()) 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()); player_status.total_time.ToDoubleS());
if (player_status.audio_format.IsDefined()) if (player_status.audio_format.IsDefined())
r.Format(COMMAND_STATUS_AUDIO ": %s\n", r.Fmt(FMT_STRING(COMMAND_STATUS_AUDIO ": {}\n"),
ToString(player_status.audio_format).c_str()); ToString(player_status.audio_format));
} }
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
...@@ -193,23 +195,23 @@ handle_status(Client &client, [[maybe_unused]] Request args, Response &r) ...@@ -193,23 +195,23 @@ handle_status(Client &client, [[maybe_unused]] Request args, Response &r)
? update_service->GetId() ? update_service->GetId()
: 0; : 0;
if (updateJobId != 0) { if (updateJobId != 0) {
r.Format(COMMAND_STATUS_UPDATING_DB ": %i\n", r.Fmt(FMT_STRING(COMMAND_STATUS_UPDATING_DB ": {}\n"),
updateJobId); updateJobId);
} }
#endif #endif
try { try {
pc.LockCheckRethrowError(); pc.LockCheckRethrowError();
} catch (...) { } catch (...) {
r.Format(COMMAND_STATUS_ERROR ": %s\n", r.Fmt(FMT_STRING(COMMAND_STATUS_ERROR ": {}\n"),
GetFullMessage(std::current_exception()).c_str()); GetFullMessage(std::current_exception()));
} }
song = playlist.GetNextPosition(); song = playlist.GetNextPosition();
if (song >= 0) if (song >= 0)
r.Format(COMMAND_STATUS_NEXTSONG ": %i\n" r.Fmt(FMT_STRING(COMMAND_STATUS_NEXTSONG ": {}\n"
COMMAND_STATUS_NEXTSONGID ": %u\n", COMMAND_STATUS_NEXTSONGID ": {}\n"),
song, playlist.PositionToId(song)); song, playlist.PositionToId(song));
return CommandResult::OK; return CommandResult::OK;
} }
...@@ -351,7 +353,7 @@ CommandResult ...@@ -351,7 +353,7 @@ CommandResult
handle_replay_gain_status(Client &client, [[maybe_unused]] Request args, handle_replay_gain_status(Client &client, [[maybe_unused]] Request args,
Response &r) Response &r)
{ {
r.Format("replay_gain_mode: %s\n", r.Fmt(FMT_STRING("replay_gain_mode: {}\n"),
ToString(client.GetPartition().replay_gain_mode)); ToString(client.GetPartition().replay_gain_mode));
return CommandResult::OK; return CommandResult::OK;
} }
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include "util/UriExtract.hxx" #include "util/UriExtract.hxx"
#include "LocateUri.hxx" #include "LocateUri.hxx"
#include <fmt/format.h>
bool bool
playlist_commands_available() noexcept playlist_commands_available() noexcept
{ {
...@@ -52,7 +54,7 @@ static void ...@@ -52,7 +54,7 @@ static void
print_spl_list(Response &r, const PlaylistVector &list) print_spl_list(Response &r, const PlaylistVector &list)
{ {
for (const auto &i : 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)) if (!IsNegative(i.mtime))
time_print(r, "Last-Modified", i.mtime); time_print(r, "Last-Modified", i.mtime);
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include "util/StringAPI.hxx" #include "util/StringAPI.hxx"
#include "util/NumberParser.hxx" #include "util/NumberParser.hxx"
#include <fmt/format.h>
#include <limits> #include <limits>
static void static void
...@@ -127,7 +129,7 @@ handle_addid(Client &client, Request args, Response &r) ...@@ -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; return CommandResult::OK;
} }
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#define __STDC_FORMAT_MACROS /* for PRIu64 */
#include "config.h" #include "config.h"
#include "StorageCommands.hxx" #include "StorageCommands.hxx"
#include "Request.hxx" #include "Request.hxx"
...@@ -37,7 +35,8 @@ ...@@ -37,7 +35,8 @@
#include "TimePrint.hxx" #include "TimePrint.hxx"
#include "IdleFlags.hxx" #include "IdleFlags.hxx"
#include <cinttypes> /* for PRIu64 */ #include <fmt/format.h>
#include <memory> #include <memory>
gcc_pure gcc_pure
...@@ -47,13 +46,6 @@ skip_path(const char *name_utf8) noexcept ...@@ -47,13 +46,6 @@ skip_path(const char *name_utf8) noexcept
return std::strchr(name_utf8, '\n') != nullptr; 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 static void
handle_listfiles_storage(Response &r, StorageDirectoryReader &reader) handle_listfiles_storage(Response &r, StorageDirectoryReader &reader)
{ {
...@@ -75,14 +67,14 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader) ...@@ -75,14 +67,14 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader)
continue; continue;
case StorageFileInfo::Type::REGULAR: case StorageFileInfo::Type::REGULAR:
r.Format("file: %s\n" r.Fmt(FMT_STRING("file: {}\n"
"size: %" PRIu64 "\n", "size: {}\n"),
name_utf8, name_utf8,
info.size); info.size);
break; break;
case StorageFileInfo::Type::DIRECTORY: case StorageFileInfo::Type::DIRECTORY:
r.Format("directory: %s\n", name_utf8); r.Fmt(FMT_STRING("directory: {}\n"), name_utf8);
break; break;
} }
...@@ -139,7 +131,7 @@ print_storage_uri(Client &client, Response &r, const Storage &storage) ...@@ -139,7 +131,7 @@ print_storage_uri(Client &client, Response &r, const Storage &storage)
uri = std::move(allocated); uri = std::move(allocated);
} }
r.Format("storage: %s\n", uri.c_str()); r.Fmt(FMT_STRING("storage: {}\n"), uri);
} }
CommandResult CommandResult
...@@ -155,7 +147,7 @@ handle_listmounts(Client &client, [[maybe_unused]] Request args, Response &r) ...@@ -155,7 +147,7 @@ handle_listmounts(Client &client, [[maybe_unused]] Request args, Response &r)
const auto visitor = [&client, &r](const char *mount_uri, const auto visitor = [&client, &r](const char *mount_uri,
const Storage &storage){ const Storage &storage){
r.Format("mount: %s\n", mount_uri); r.Fmt(FMT_STRING("mount: {}\n"), mount_uri);
print_storage_uri(client, r, storage); print_storage_uri(client, r, storage);
}; };
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "tag/VisitFallback.hxx" #include "tag/VisitFallback.hxx"
#include "TagPrint.hxx" #include "TagPrint.hxx"
#include <fmt/format.h>
#include <functional> #include <functional>
#include <map> #include <map>
...@@ -47,9 +49,9 @@ PrintSearchStats(Response &r, const SearchStats &stats) noexcept ...@@ -47,9 +49,9 @@ PrintSearchStats(Response &r, const SearchStats &stats) noexcept
unsigned total_duration_s = unsigned total_duration_s =
std::chrono::duration_cast<std::chrono::seconds>(stats.total_duration).count(); std::chrono::duration_cast<std::chrono::seconds>(stats.total_duration).count();
r.Format("songs: %u\n" r.Fmt(FMT_STRING("songs: {}\n"
"playtime: %u\n", "playtime: {}\n"),
stats.n_songs, total_duration_s); stats.n_songs, total_duration_s);
} }
static void static void
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include "time/ChronoUtil.hxx" #include "time/ChronoUtil.hxx"
#include "util/RecursiveMap.hxx" #include "util/RecursiveMap.hxx"
#include <fmt/format.h>
#include <functional> #include <functional>
gcc_pure gcc_pure
...@@ -47,8 +49,8 @@ static void ...@@ -47,8 +49,8 @@ static void
PrintDirectoryURI(Response &r, bool base, PrintDirectoryURI(Response &r, bool base,
const LightDirectory &directory) noexcept const LightDirectory &directory) noexcept
{ {
r.Format("directory: %s\n", r.Fmt(FMT_STRING("directory: {}\n"),
ApplyBaseFlag(directory.GetPath(), base)); ApplyBaseFlag(directory.GetPath(), base));
} }
static void static void
...@@ -77,11 +79,11 @@ print_playlist_in_directory(Response &r, bool base, ...@@ -77,11 +79,11 @@ print_playlist_in_directory(Response &r, bool base,
const char *name_utf8) noexcept const char *name_utf8) noexcept
{ {
if (base || directory == nullptr) if (base || directory == nullptr)
r.Format("playlist: %s\n", r.Fmt(FMT_STRING("playlist: {}\n"),
ApplyBaseFlag(name_utf8, base)); ApplyBaseFlag(name_utf8, base));
else else
r.Format("playlist: %s/%s\n", r.Fmt(FMT_STRING("playlist: {}/{}\n"),
directory, name_utf8); directory, name_utf8);
} }
static void static void
...@@ -90,10 +92,10 @@ print_playlist_in_directory(Response &r, bool base, ...@@ -90,10 +92,10 @@ print_playlist_in_directory(Response &r, bool base,
const char *name_utf8) noexcept const char *name_utf8) noexcept
{ {
if (base || directory == nullptr || directory->IsRoot()) if (base || directory == nullptr || directory->IsRoot())
r.Format("playlist: %s\n", name_utf8); r.Fmt(FMT_STRING("playlist: {}\n"), name_utf8);
else else
r.Format("playlist: %s/%s\n", r.Fmt(FMT_STRING("playlist: {}/{}\n"),
directory->GetPath(), name_utf8); directory->GetPath(), name_utf8);
} }
static void static void
...@@ -196,7 +198,7 @@ PrintUniqueTags(Response &r, ConstBuffer<TagType> tag_types, ...@@ -196,7 +198,7 @@ PrintUniqueTags(Response &r, ConstBuffer<TagType> tag_types,
tag_types.pop_front(); tag_types.pop_front();
for (const auto &[key, tag] : map) { 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()) if (!tag_types.empty())
PrintUniqueTags(r, tag_types, tag); PrintUniqueTags(r, tag_types, tag);
......
...@@ -55,6 +55,7 @@ db_glue = static_library( ...@@ -55,6 +55,7 @@ db_glue = static_library(
include_directories: inc, include_directories: inc,
dependencies: [ dependencies: [
boost_dep, boost_dep,
fmt_dep,
log_dep, log_dep,
], ],
) )
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "DecoderPlugin.hxx" #include "DecoderPlugin.hxx"
#include "client/Response.hxx" #include "client/Response.hxx"
#include <fmt/format.h>
#include <cassert> #include <cassert>
#include <functional> #include <functional>
...@@ -33,15 +35,15 @@ decoder_plugin_print(Response &r, ...@@ -33,15 +35,15 @@ decoder_plugin_print(Response &r,
assert(plugin.name != nullptr); assert(plugin.name != nullptr);
r.Format("plugin: %s\n", plugin.name); r.Fmt(FMT_STRING("plugin: {}\n"), plugin.name);
if (plugin.suffixes != nullptr) if (plugin.suffixes != nullptr)
for (p = plugin.suffixes; *p != nullptr; ++p) 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) if (plugin.mime_types != nullptr)
for (p = plugin.mime_types; *p != nullptr; ++p) for (p = plugin.mime_types; *p != nullptr; ++p)
r.Format("mime_type: %s\n", *p); r.Fmt(FMT_STRING("mime_type: {}\n"), *p);
} }
void void
......
...@@ -26,8 +26,9 @@ ...@@ -26,8 +26,9 @@
#include "client/Response.hxx" #include "client/Response.hxx"
#include "util/UriExtract.hxx" #include "util/UriExtract.hxx"
#include <cassert> #include <fmt/format.h>
#include <cassert>
#include <string> #include <string>
void print_supported_uri_schemes_to_fp(FILE *fp) void print_supported_uri_schemes_to_fp(FILE *fp)
...@@ -67,7 +68,7 @@ print_supported_uri_schemes(Response &r) ...@@ -67,7 +68,7 @@ print_supported_uri_schemes(Response &r)
}); });
for (const auto& protocol : protocols) { for (const auto& protocol : protocols) {
r.Format("handler: %s\n", protocol.c_str()); r.Fmt(FMT_STRING("handler: {}\n"), protocol);
} }
} }
......
...@@ -26,21 +26,24 @@ ...@@ -26,21 +26,24 @@
#include "MultipleOutputs.hxx" #include "MultipleOutputs.hxx"
#include "client/Response.hxx" #include "client/Response.hxx"
#include <fmt/format.h>
void void
printAudioDevices(Response &r, const MultipleOutputs &outputs) printAudioDevices(Response &r, const MultipleOutputs &outputs)
{ {
for (unsigned i = 0, n = outputs.Size(); i != n; ++i) { for (unsigned i = 0, n = outputs.Size(); i != n; ++i) {
const auto &ao = outputs.Get(i); const auto &ao = outputs.Get(i);
r.Format("outputid: %u\n" r.Fmt(FMT_STRING("outputid: {}\n"
"outputname: %s\n" "outputname: {}\n"
"plugin: %s\n" "plugin: {}\n"
"outputenabled: %i\n", "outputenabled: {}\n"),
i, i,
ao.GetName(), ao.GetPluginName(), ao.GetName(), ao.GetPluginName(),
ao.IsEnabled()); ao.IsEnabled());
for (const auto &[attribute, value] : ao.GetAttributes()) 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);
} }
} }
...@@ -35,6 +35,9 @@ output_glue = static_library( ...@@ -35,6 +35,9 @@ output_glue = static_library(
'Finish.cxx', 'Finish.cxx',
'Init.cxx', 'Init.cxx',
include_directories: inc, include_directories: inc,
dependencies: [
fmt_dep,
],
) )
output_glue_dep = declare_dependency( output_glue_dep = declare_dependency(
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "song/LightSong.hxx" #include "song/LightSong.hxx"
#include "client/Response.hxx" #include "client/Response.hxx"
#include <fmt/format.h>
/** /**
* Send detailed information about a range of songs in the queue to a * Send detailed information about a range of songs in the queue to a
* client. * client.
...@@ -38,12 +40,12 @@ queue_print_song_info(Response &r, const Queue &queue, ...@@ -38,12 +40,12 @@ queue_print_song_info(Response &r, const Queue &queue,
unsigned position) unsigned position)
{ {
song_print_info(r, queue.Get(position)); song_print_info(r, queue.Get(position));
r.Format("Pos: %u\nId: %u\n", r.Fmt(FMT_STRING("Pos: {}\nId: {}\n"),
position, queue.PositionToId(position)); position, queue.PositionToId(position));
uint8_t priority = queue.GetPriorityAtPosition(position); uint8_t priority = queue.GetPriorityAtPosition(position);
if (priority != 0) if (priority != 0)
r.Format("Prio: %u\n", priority); r.Fmt(FMT_STRING("Prio: {}\n"), priority);
} }
void void
...@@ -65,7 +67,7 @@ queue_print_uris(Response &r, const Queue &queue, ...@@ -65,7 +67,7 @@ queue_print_uris(Response &r, const Queue &queue,
assert(end <= queue.GetLength()); assert(end <= queue.GetLength());
for (unsigned i = start; i < end; ++i) { for (unsigned i = start; i < end; ++i) {
r.Format("%i:", i); r.Fmt(FMT_STRING("{}:"), i);
song_print_uri(r, queue.Get(i)); song_print_uri(r, queue.Get(i));
} }
} }
...@@ -93,8 +95,8 @@ queue_print_changes_position(Response &r, const Queue &queue, ...@@ -93,8 +95,8 @@ queue_print_changes_position(Response &r, const Queue &queue,
for (unsigned i = start; i < end; i++) for (unsigned i = start; i < end; i++)
if (queue.IsNewerAtPosition(i, version)) if (queue.IsNewerAtPosition(i, version))
r.Format("cpos: %i\nId: %i\n", r.Fmt(FMT_STRING("cpos: {}\nId: {}\n"),
i, queue.PositionToId(i)); i, queue.PositionToId(i));
} }
void void
......
...@@ -21,11 +21,13 @@ ...@@ -21,11 +21,13 @@
#include "Sticker.hxx" #include "Sticker.hxx"
#include "client/Response.hxx" #include "client/Response.hxx"
#include <fmt/format.h>
void void
sticker_print_value(Response &r, sticker_print_value(Response &r,
const char *name, const char *value) const char *name, const char *value)
{ {
r.Format("sticker: %s=%s\n", name, value); r.Fmt(FMT_STRING("sticker: {}={}\n"), name, value);
} }
void void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment