diff options
author | Max Kellermann <max@musicpd.org> | 2018-01-24 12:52:43 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2018-07-06 19:07:02 +0200 |
commit | 60d5bf0240dea58419edb05198906349e81abbe8 (patch) | |
tree | 3811d24f1ec17257b14d7dd8759a6948ac676399 | |
parent | 41cdc4e14b3d36d70039a7ac1578fe7c898a0bac (diff) |
util/StringFormat: new utility library
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/AudioFormat.cxx | 19 | ||||
-rw-r--r-- | src/db/plugins/upnp/ContentDirectoryService.cxx | 17 | ||||
-rw-r--r-- | src/decoder/plugins/GmeDecoderPlugin.cxx | 26 | ||||
-rw-r--r-- | src/decoder/plugins/SidplayDecoderPlugin.cxx | 14 | ||||
-rw-r--r-- | src/fs/io/FileOutputStream.cxx | 8 | ||||
-rw-r--r-- | src/input/plugins/CurlInputPlugin.cxx | 21 | ||||
-rw-r--r-- | src/lib/ffmpeg/LogCallback.cxx | 8 | ||||
-rw-r--r-- | src/output/Init.cxx | 1 | ||||
-rw-r--r-- | src/protocol/Ack.hxx | 10 | ||||
-rw-r--r-- | src/storage/plugins/CurlStorage.cxx | 5 | ||||
-rw-r--r-- | src/tag/TagHandler.cxx | 9 | ||||
-rw-r--r-- | src/thread/Name.hxx | 6 | ||||
-rw-r--r-- | src/util/StringFormat.hxx | 69 |
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 |