util/FormatString: new library to replace g_strdup_printf()

This commit is contained in:
Max Kellermann 2013-10-19 16:58:45 +02:00
parent 1434e5a22e
commit 5dc4cbdf82
8 changed files with 151 additions and 66 deletions

View File

@ -246,6 +246,7 @@ libutil_a_SOURCES = \
src/util/Domain.hxx \
src/util/ReusableArray.hxx \
src/util/StringUtil.cxx src/util/StringUtil.hxx \
src/util/FormatString.cxx src/util/FormatString.hxx \
src/util/Tokenizer.cxx src/util/Tokenizer.hxx \
src/util/UriUtil.cxx src/util/UriUtil.hxx \
src/util/Manual.hxx \

View File

@ -19,11 +19,9 @@
#include "config.h"
#include "ClientInternal.hxx"
#include <glib.h>
#include "util/FormatString.hxx"
#include <string.h>
#include <stdio.h>
/**
* Write a block of data to the client.
@ -47,34 +45,9 @@ client_puts(Client *client, const char *s)
void
client_vprintf(Client *client, const char *fmt, va_list args)
{
#ifndef WIN32
va_list tmp;
int length;
va_copy(tmp, args);
length = vsnprintf(NULL, 0, fmt, tmp);
va_end(tmp);
if (length <= 0)
/* wtf.. */
return;
char *buffer = (char *)g_malloc(length + 1);
vsnprintf(buffer, length + 1, fmt, args);
client_write(client, buffer, length);
g_free(buffer);
#else
/* On mingw32, snprintf() expects a 64 bit integer instead of
a "long int" for "%li". This is not consistent with our
expectation, so we're using plain sprintf() here, hoping
the static buffer is large enough. Sorry for this hack,
but WIN32 development is so painful, I'm not in the mood to
do it properly now. */
static char buffer[4096];
vsprintf(buffer, fmt, args);
client_write(client, buffer, strlen(buffer));
#endif
char *p = FormatNewV(fmt, args);
client_write(client, p, strlen(p));
delete[] p;
}
void

View File

@ -21,6 +21,7 @@
#include "IcyMetaDataServer.hxx"
#include "Page.hxx"
#include "tag/Tag.hxx"
#include "util/FormatString.hxx"
#include <glib.h>
@ -32,26 +33,26 @@ icy_server_metadata_header(const char *name,
const char *genre, const char *url,
const char *content_type, int metaint)
{
return g_strdup_printf("ICY 200 OK\r\n"
"icy-notice1:<BR>This stream requires an audio player!<BR>\r\n" /* TODO */
"icy-notice2:MPD - The music player daemon<BR>\r\n"
"icy-name: %s\r\n" /* TODO */
"icy-genre: %s\r\n" /* TODO */
"icy-url: %s\r\n" /* TODO */
"icy-pub:1\r\n"
"icy-metaint:%d\r\n"
/* TODO "icy-br:%d\r\n" */
"Content-Type: %s\r\n"
"Connection: close\r\n"
"Pragma: no-cache\r\n"
"Cache-Control: no-cache, no-store\r\n"
"\r\n",
name,
genre,
url,
metaint,
/* bitrate, */
content_type);
return FormatNew("ICY 200 OK\r\n"
"icy-notice1:<BR>This stream requires an audio player!<BR>\r\n" /* TODO */
"icy-notice2:MPD - The music player daemon<BR>\r\n"
"icy-name: %s\r\n" /* TODO */
"icy-genre: %s\r\n" /* TODO */
"icy-url: %s\r\n" /* TODO */
"icy-pub:1\r\n"
"icy-metaint:%d\r\n"
/* TODO "icy-br:%d\r\n" */
"Content-Type: %s\r\n"
"Connection: close\r\n"
"Pragma: no-cache\r\n"
"Cache-Control: no-cache, no-store\r\n"
"\r\n",
name,
genre,
url,
metaint,
/* bitrate, */
content_type);
}
static char *
@ -61,12 +62,10 @@ icy_server_metadata_string(const char *stream_title, const char* stream_url)
guint meta_length;
// The leading n is a placeholder for the length information
icy_metadata = g_strdup_printf("nStreamTitle='%s';"
"StreamUrl='%s';",
stream_title,
stream_url);
g_return_val_if_fail(icy_metadata, NULL);
icy_metadata = FormatNew("nStreamTitle='%s';"
"StreamUrl='%s';",
stream_title,
stream_url);
meta_length = strlen(icy_metadata);
@ -77,7 +76,7 @@ icy_server_metadata_string(const char *stream_title, const char* stream_url)
icy_metadata[0] = meta_length;
if (meta_length > 255) {
g_free(icy_metadata);
delete[] icy_metadata;
return NULL;
}
@ -130,7 +129,7 @@ icy_server_metadata_page(const Tag &tag, const enum tag_type *types)
Page *icy_metadata = Page::Copy(icy_string, (icy_string[0] * 16) + 1);
g_free(icy_string);
delete[] icy_string;
return icy_metadata;
}

View File

@ -25,6 +25,9 @@
struct Tag;
class Page;
/**
* Free the return value with delete[].
*/
char*
icy_server_metadata_header(const char *name,
const char *genre, const char *url,

View File

@ -22,6 +22,7 @@
#include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx"
#include "util/FormatString.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@ -122,9 +123,8 @@ gme_container_scan(const char *path_fs, const unsigned int tnum)
const char *subtune_suffix = uri_get_suffix(path_fs);
if (tnum <= num_songs){
char *subtune = g_strdup_printf(
SUBTUNE_PREFIX "%03u.%s", tnum, subtune_suffix);
return subtune;
return FormatNew(SUBTUNE_PREFIX "%03u.%s",
tnum, subtune_suffix);
} else
return nullptr;
}

View File

@ -146,9 +146,7 @@ HttpdClient::SendResponse()
httpd->content_type);
} else if (metadata_requested) {
gchar *metadata_header;
metadata_header =
char *metadata_header =
icy_server_metadata_header(httpd->name, httpd->genre,
httpd->website,
httpd->content_type,
@ -156,7 +154,7 @@ HttpdClient::SendResponse()
g_strlcpy(buffer, metadata_header, sizeof(buffer));
g_free(metadata_header);
delete[] metadata_header;
} else { /* revert to a normal HTTP request */
snprintf(buffer, sizeof(buffer),

68
src/util/FormatString.cxx Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "FormatString.hxx"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *
FormatNewV(const char *fmt, va_list args)
{
#ifndef WIN32
va_list tmp;
va_copy(tmp, args);
const int length = vsnprintf(NULL, 0, fmt, tmp);
va_end(tmp);
if (length <= 0)
/* wtf.. */
abort();
char *buffer = new char[length + 1];
vsnprintf(buffer, length + 1, fmt, args);
return buffer;
#else
/* On mingw32, snprintf() expects a 64 bit integer instead of
a "long int" for "%li". This is not consistent with our
expectation, so we're using plain sprintf() here, hoping
the static buffer is large enough. Sorry for this hack,
but WIN32 development is so painful, I'm not in the mood to
do it properly now. */
char buffer[16384];
vsprintf(buffer, fmt, args);
const size_t length = strlen(buffer);
char *p = new char[length + 1];
memcpy(p, buffer, length + 1);
return p;
#endif
}
char *
FormatNew(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
char *p = FormatNewV(fmt, args);
va_end(args);
return p;
}

43
src/util/FormatString.hxx Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_FORMAT_STRING_HXX
#define MPD_FORMAT_STRING_HXX
#include "Compiler.h"
#include <stdarg.h>
/**
* Format into a newly allocated string. The caller frees the return
* value with delete[].
*/
gcc_malloc gcc_nonnull_all
char *
FormatNewV(const char *fmt, va_list args);
/**
* Format into a newly allocated string. The caller frees the return
* value with delete[].
*/
gcc_malloc gcc_nonnull(1) gcc_printf(1,2)
char *
FormatNew(const char *fmt, ...);
#endif