util/StringFormat: new utility library
This commit is contained in:
parent
41cdc4e14b
commit
60d5bf0240
@ -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 \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
69
src/util/StringFormat.hxx
Normal file
69
src/util/StringFormat.hxx
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user