summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-01-24 12:52:43 +0100
committerMax Kellermann <max@musicpd.org>2018-07-06 19:07:02 +0200
commit60d5bf0240dea58419edb05198906349e81abbe8 (patch)
tree3811d24f1ec17257b14d7dd8759a6948ac676399
parent41cdc4e14b3d36d70039a7ac1578fe7c898a0bac (diff)
util/StringFormat: new utility library
-rw-r--r--Makefile.am1
-rw-r--r--src/AudioFormat.cxx19
-rw-r--r--src/db/plugins/upnp/ContentDirectoryService.cxx17
-rw-r--r--src/decoder/plugins/GmeDecoderPlugin.cxx26
-rw-r--r--src/decoder/plugins/SidplayDecoderPlugin.cxx14
-rw-r--r--src/fs/io/FileOutputStream.cxx8
-rw-r--r--src/input/plugins/CurlInputPlugin.cxx21
-rw-r--r--src/lib/ffmpeg/LogCallback.cxx8
-rw-r--r--src/output/Init.cxx1
-rw-r--r--src/protocol/Ack.hxx10
-rw-r--r--src/storage/plugins/CurlStorage.cxx5
-rw-r--r--src/tag/TagHandler.cxx9
-rw-r--r--src/thread/Name.hxx6
-rw-r--r--src/util/StringFormat.hxx69
14 files changed, 132 insertions, 82 deletions
diff --git a/Makefile.am b/Makefile.am
index d5416681a..c14823910 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -444,6 +444,7 @@ libutil_a_SOURCES = \
src/util/NumberParser.hxx \
src/util/MimeType.cxx src/util/MimeType.hxx \
src/util/StringBuffer.hxx \
+ src/util/StringFormat.hxx \
src/util/StringPointer.hxx \
src/util/StringView.cxx src/util/StringView.hxx \
src/util/AllocatedString.cxx src/util/AllocatedString.hxx \
diff --git a/src/AudioFormat.cxx b/src/AudioFormat.cxx
index f317d8abe..13d3709f9 100644
--- a/src/AudioFormat.cxx
+++ b/src/AudioFormat.cxx
@@ -19,9 +19,9 @@
#include "AudioFormat.hxx"
#include "util/StringBuffer.hxx"
+#include "util/StringFormat.hxx"
#include <assert.h>
-#include <stdio.h>
void
AudioFormat::ApplyMask(AudioFormat mask) noexcept
@@ -44,21 +44,16 @@ AudioFormat::ApplyMask(AudioFormat mask) noexcept
StringBuffer<24>
ToString(const AudioFormat af) noexcept
{
- StringBuffer<24> buffer;
-
if (af.format == SampleFormat::DSD && af.sample_rate > 0 &&
af.sample_rate % 44100 == 0) {
/* use shortcuts such as "dsd64" which implies the
sample rate */
- snprintf(buffer.data(), buffer.capacity(), "dsd%u:%u",
- af.sample_rate * 8 / 44100,
- af.channels);
- return buffer;
+ return StringFormat<24>("dsd%u:%u",
+ af.sample_rate * 8 / 44100,
+ af.channels);
}
- snprintf(buffer.data(), buffer.capacity(), "%u:%s:%u",
- af.sample_rate, sample_format_to_string(af.format),
- af.channels);
-
- return buffer;
+ return StringFormat<24>("%u:%s:%u",
+ af.sample_rate, sample_format_to_string(af.format),
+ af.channels);
}
diff --git a/src/db/plugins/upnp/ContentDirectoryService.cxx b/src/db/plugins/upnp/ContentDirectoryService.cxx
index 386a1fcaa..d7aeca82d 100644
--- a/src/db/plugins/upnp/ContentDirectoryService.cxx
+++ b/src/db/plugins/upnp/ContentDirectoryService.cxx
@@ -27,6 +27,7 @@
#include "util/UriUtil.hxx"
#include "util/RuntimeError.hxx"
#include "util/ScopeExit.hxx"
+#include "util/StringFormat.hxx"
#include <stdio.h>
@@ -47,10 +48,6 @@ ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl,
unsigned &didreadp,
unsigned &totalp) const
{
- // Create request
- char ofbuf[100], cntbuf[100];
- sprintf(ofbuf, "%u", offset);
- sprintf(cntbuf, "%u", count);
// Some devices require an empty SortCriteria, else bad params
IXML_Document *request =
MakeActionHelper("Browse", m_serviceType.c_str(),
@@ -58,8 +55,10 @@ ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl,
"BrowseFlag", "BrowseDirectChildren",
"Filter", "*",
"SortCriteria", "",
- "StartingIndex", ofbuf,
- "RequestedCount", cntbuf);
+ "StartingIndex",
+ StringFormat<32>("%u", offset).c_str(),
+ "RequestedCount",
+ StringFormat<32>("%u", count).c_str());
if (request == nullptr)
throw std::runtime_error("UpnpMakeAction() failed");
@@ -112,15 +111,13 @@ ContentDirectoryService::search(UpnpClient_Handle hdl,
unsigned offset = 0, total = -1, count;
do {
- char ofbuf[100];
- sprintf(ofbuf, "%d", offset);
-
UniqueIxmlDocument request(MakeActionHelper("Search", m_serviceType.c_str(),
"ContainerID", objectId,
"SearchCriteria", ss,
"Filter", "*",
"SortCriteria", "",
- "StartingIndex", ofbuf,
+ "StartingIndex",
+ StringFormat<32>("%u", offset).c_str(),
"RequestedCount", "0")); // Setting a value here gets twonky into fits
if (!request)
throw std::runtime_error("UpnpMakeAction() failed");
diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx
index 1b9d06163..ba0daba63 100644
--- a/src/decoder/plugins/GmeDecoderPlugin.cxx
+++ b/src/decoder/plugins/GmeDecoderPlugin.cxx
@@ -28,7 +28,7 @@
#include "fs/Path.hxx"
#include "fs/AllocatedPath.hxx"
#include "util/ScopeExit.hxx"
-#include "util/FormatString.hxx"
+#include "util/StringFormat.hxx"
#include "util/UriUtil.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
@@ -38,7 +38,6 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
#define SUBTUNE_PREFIX "tune_"
@@ -191,20 +190,17 @@ ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count,
tag_handler_invoke_duration(handler, handler_ctx,
SongTime::FromMS(info.play_length));
- if (track_count > 1) {
- char track[16];
- sprintf(track, "%u", song_num + 1);
- tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track);
- }
+ if (track_count > 1)
+ tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK,
+ StringFormat<16>("%u", song_num + 1));
if (info.song != nullptr) {
if (track_count > 1) {
/* start numbering subtunes from 1 */
- char tag_title[1024];
- snprintf(tag_title, sizeof(tag_title),
- "%s (%u/%d)",
- info.song, song_num + 1,
- track_count);
+ const auto tag_title =
+ StringFormat<1024>("%s (%u/%d)",
+ info.song, song_num + 1,
+ track_count);
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, tag_title);
} else
@@ -297,9 +293,9 @@ gme_container_scan(Path path_fs)
ScanMusicEmu(emu, i,
add_tag_handler, &tag_builder);
- char track_name[64];
- snprintf(track_name, sizeof(track_name),
- SUBTUNE_PREFIX "%03u.%s", i+1, subtune_suffix);
+ const auto track_name =
+ StringFormat<64>(SUBTUNE_PREFIX "%03u.%s", i+1,
+ subtune_suffix);
tail = list.emplace_after(tail, track_name,
tag_builder.Commit());
}
diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx
index 3a3c712ef..fc2390ded 100644
--- a/src/decoder/plugins/SidplayDecoderPlugin.cxx
+++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx
@@ -26,7 +26,7 @@
#include "fs/Path.hxx"
#include "fs/AllocatedPath.hxx"
#include "util/Macros.hxx"
-#include "util/FormatString.hxx"
+#include "util/StringFormat.hxx"
#include "util/Domain.hxx"
#include "system/ByteOrder.hxx"
#include "Log.hxx"
@@ -413,10 +413,9 @@ ScanSidTuneInfo(const SidTuneInfo &info, unsigned track, unsigned n_tracks,
title = "";
if (n_tracks > 1) {
- char tag_title[1024];
- snprintf(tag_title, sizeof(tag_title),
- "%s (%u/%u)",
- title, track, n_tracks);
+ const auto tag_title =
+ StringFormat<1024>("%s (%u/%u)",
+ title, track, n_tracks);
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, tag_title);
} else
@@ -435,9 +434,8 @@ ScanSidTuneInfo(const SidTuneInfo &info, unsigned track, unsigned n_tracks,
date);
/* track */
- char track_buffer[16];
- sprintf(track_buffer, "%d", track);
- tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track_buffer);
+ tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK,
+ StringFormat<16>("%u", track));
}
static bool
diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index ddf7208a7..e9ce40387 100644
--- a/src/fs/io/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
@@ -20,6 +20,7 @@
#include "config.h"
#include "FileOutputStream.hxx"
#include "system/Error.hxx"
+#include "util/StringFormat.hxx"
FileOutputStream::FileOutputStream(Path _path, Mode _mode)
:path(_path), mode(_mode)
@@ -212,10 +213,9 @@ FileOutputStream::Commit()
unlink(GetPath().c_str());
/* hard-link the temporary file to the final path */
- char fd_path[64];
- snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%d",
- fd.Get());
- if (linkat(AT_FDCWD, fd_path, AT_FDCWD, path.c_str(),
+ if (linkat(AT_FDCWD,
+ StringFormat<64>("/proc/self/fd/%d", fd.Get()),
+ AT_FDCWD, path.c_str(),
AT_SYMLINK_FOLLOW) < 0)
throw FormatErrno("Failed to commit %s",
path.c_str());
diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx
index ea48d299b..6e1cf42f2 100644
--- a/src/input/plugins/CurlInputPlugin.cxx
+++ b/src/input/plugins/CurlInputPlugin.cxx
@@ -34,6 +34,7 @@
#include "IOThread.hxx"
#include "util/ASCII.hxx"
#include "util/StringUtil.hxx"
+#include "util/StringFormat.hxx"
#include "util/NumberParser.hxx"
#include "util/RuntimeError.hxx"
#include "util/Domain.hxx"
@@ -373,13 +374,10 @@ CurlInputStream::InitEasy()
if (proxy_port > 0)
request->SetOption(CURLOPT_PROXYPORT, (long)proxy_port);
- if (proxy_user != nullptr && proxy_password != nullptr) {
- char proxy_auth_str[1024];
- snprintf(proxy_auth_str, sizeof(proxy_auth_str),
- "%s:%s",
- proxy_user, proxy_password);
- request->SetOption(CURLOPT_PROXYUSERPWD, proxy_auth_str);
- }
+ if (proxy_user != nullptr && proxy_password != nullptr)
+ request->SetOption(CURLOPT_PROXYUSERPWD,
+ StringFormat<1024>("%s:%s", proxy_user,
+ proxy_password).c_str());
request->SetOption(CURLOPT_SSL_VERIFYPEER, verify_peer ? 1l : 0l);
request->SetOption(CURLOPT_SSL_VERIFYHOST, verify_host ? 2l : 0l);
@@ -416,11 +414,10 @@ CurlInputStream::SeekInternal(offset_type new_offset)
/* send the "Range" header */
- if (offset > 0) {
- char range[32];
- sprintf(range, "%" PRIoffset "-", offset);
- request->SetOption(CURLOPT_RANGE, range);
- }
+ if (offset > 0)
+ request->SetOption(CURLOPT_RANGE,
+ StringFormat<40>("%" PRIoffset "-",
+ offset).c_str());
StartRequest();
}
diff --git a/src/lib/ffmpeg/LogCallback.cxx b/src/lib/ffmpeg/LogCallback.cxx
index c682da63d..5a0fa4a6f 100644
--- a/src/lib/ffmpeg/LogCallback.cxx
+++ b/src/lib/ffmpeg/LogCallback.cxx
@@ -25,6 +25,7 @@
#include "Domain.hxx"
#include "LogV.hxx"
#include "util/Domain.hxx"
+#include "util/StringFormat.hxx"
extern "C" {
#include <libavutil/log.h>
@@ -57,9 +58,10 @@ FfmpegLogCallback(gcc_unused void *ptr, int level, const char *fmt, va_list vl)
cls = *(const AVClass *const*)ptr;
if (cls != nullptr) {
- char domain[64];
- snprintf(domain, sizeof(domain), "%s/%s",
- ffmpeg_domain.GetName(), cls->item_name(ptr));
+ const auto domain =
+ StringFormat<64>("%s/%s",
+ ffmpeg_domain.GetName(),
+ cls->item_name(ptr));
const Domain d(domain);
LogFormatV(d, FfmpegImportLogLevel(level), fmt, vl);
}
diff --git a/src/output/Init.cxx b/src/output/Init.cxx
index 34b53d916..591219c92 100644
--- a/src/output/Init.cxx
+++ b/src/output/Init.cxx
@@ -37,6 +37,7 @@
#include "config/ConfigGlobal.hxx"
#include "config/Block.hxx"
#include "util/RuntimeError.hxx"
+#include "util/StringFormat.hxx"
#include "Log.hxx"
#include <stdexcept>
diff --git a/src/protocol/Ack.hxx b/src/protocol/Ack.hxx
index 195f4bcb0..497f85b18 100644
--- a/src/protocol/Ack.hxx
+++ b/src/protocol/Ack.hxx
@@ -20,9 +20,9 @@
#ifndef MPD_ACK_H
#define MPD_ACK_H
-#include <stdexcept>
+#include "util/StringFormat.hxx"
-#include <stdio.h>
+#include <stdexcept>
class Domain;
@@ -60,9 +60,9 @@ template<typename... Args>
static inline ProtocolError
FormatProtocolError(enum ack code, const char *fmt, Args&&... args) noexcept
{
- char buffer[256];
- snprintf(buffer, sizeof(buffer), fmt, std::forward<Args>(args)...);
- return ProtocolError(code, buffer);
+ return ProtocolError(code,
+ StringFormat<256>(fmt,
+ std::forward<Args>(args)...));
}
#endif
diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx
index 85863cb07..c077b8bb2 100644
--- a/src/storage/plugins/CurlStorage.cxx
+++ b/src/storage/plugins/CurlStorage.cxx
@@ -35,6 +35,7 @@
#include "thread/Cond.hxx"
#include "util/RuntimeError.hxx"
#include "util/StringCompare.hxx"
+#include "util/StringFormat.hxx"
#include "util/TimeParser.hxx"
#include "util/UriUtil.hxx"
@@ -296,9 +297,7 @@ public:
{
request.SetOption(CURLOPT_CUSTOMREQUEST, "PROPFIND");
- char buffer[40];
- sprintf(buffer, "depth: %u", depth);
- request_headers.Append(buffer);
+ request_headers.Append(StringFormat<40>("depth: %u", depth));
request.SetOption(CURLOPT_HTTPHEADER, request_headers.Get());
diff --git a/src/tag/TagHandler.cxx b/src/tag/TagHandler.cxx
index 345c64a21..d59ac9a9c 100644
--- a/src/tag/TagHandler.cxx
+++ b/src/tag/TagHandler.cxx
@@ -21,8 +21,8 @@
#include "TagHandler.hxx"
#include "TagBuilder.hxx"
#include "util/ASCII.hxx"
+#include "util/StringFormat.hxx"
-#include <stdio.h>
#include <stdlib.h>
static void
@@ -42,11 +42,8 @@ add_tag_tag(TagType type, const char *value, void *ctx)
/* filter out this extra data and leading zeroes */
char *end;
unsigned n = strtoul(value, &end, 10);
- if (value != end) {
- char s[21];
- if (snprintf(s, 21, "%u", n) > 0)
- tag.AddItem(type, s);
- }
+ if (value != end)
+ tag.AddItem(type, StringFormat<21>("%u", n));
} else
tag.AddItem(type, value);
}
diff --git a/src/thread/Name.hxx b/src/thread/Name.hxx
index 20560bfbb..00d5b58da 100644
--- a/src/thread/Name.hxx
+++ b/src/thread/Name.hxx
@@ -31,7 +31,7 @@
#endif
#ifdef HAVE_THREAD_NAME
-# include <stdio.h>
+#include "util/StringFormat.hxx"
#endif
static inline void
@@ -59,9 +59,7 @@ static inline void
FormatThreadName(const char *fmt, gcc_unused Args&&... args)
{
#ifdef HAVE_THREAD_NAME
- char buffer[16];
- snprintf(buffer, sizeof(buffer), fmt, args...);
- SetThreadName(buffer);
+ SetThreadName(StringFormat<16>(fmt, args...));
#else
(void)fmt;
#endif
diff --git a/src/util/StringFormat.hxx b/src/util/StringFormat.hxx
new file mode 100644
index 000000000..4fee2fc37
--- /dev/null
+++ b/src/util/StringFormat.hxx
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010-2015 Max Kellermann <max.kellermann@gmail.com>
+ *
+ * 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.
+ */
+
+#ifndef STRING_FORMAT_HXX
+#define STRING_FORMAT_HXX
+
+#include "StringBuffer.hxx"
+
+#include <stdio.h>
+
+template<typename... Args>
+static inline void
+StringFormat(char *buffer, size_t size,
+ const char *fmt, Args&&... args) noexcept
+{
+ snprintf(buffer, size, fmt, args...);
+}
+
+template<size_t CAPACITY, typename... Args>
+static inline void
+StringFormat(StringBuffer<CAPACITY> &buffer,
+ const char *fmt, Args&&... args) noexcept
+{
+ StringFormat(buffer.data(), buffer.capacity(), fmt, args...);
+}
+
+template<size_t CAPACITY, typename... Args>
+static inline StringBuffer<CAPACITY>
+StringFormat(const char *fmt, Args&&... args) noexcept
+{
+ StringBuffer<CAPACITY> result;
+ StringFormat(result, fmt, args...);
+ return result;
+}
+
+template<typename... Args>
+static inline void
+StringFormatUnsafe(char *buffer, const char *fmt, Args&&... args) noexcept
+{
+ sprintf(buffer, fmt, args...);
+}
+
+#endif