mirror of
https://github.com/transmission/transmission
synced 2025-02-22 14:10:34 +00:00
mike.dld's portability improvements to libtransmission, pt 1
This commit is contained in:
parent
650091aed7
commit
92daae473e
8 changed files with 557 additions and 16 deletions
|
@ -458,6 +458,8 @@
|
|||
BEFC1E560C07861A00B0BB3C /* completion.c in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1E1D0C07861A00B0BB3C /* completion.c */; };
|
||||
BEFC1E570C07861A00B0BB3C /* clients.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1E1E0C07861A00B0BB3C /* clients.h */; };
|
||||
BEFC1E580C07861A00B0BB3C /* clients.c in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1E1F0C07861A00B0BB3C /* clients.c */; };
|
||||
C1077A4E183EB29600634C22 /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = C1077A4A183EB29600634C22 /* error.c */; };
|
||||
C1077A4F183EB29600634C22 /* error.h in Headers */ = {isa = PBXBuildFile; fileRef = C1077A4B183EB29600634C22 /* error.h */; };
|
||||
D4AF3B2F0C41F7A500D46B6B /* list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4AF3B2D0C41F7A500D46B6B /* list.c */; };
|
||||
D4AF3B300C41F7A600D46B6B /* list.h in Headers */ = {isa = PBXBuildFile; fileRef = D4AF3B2E0C41F7A500D46B6B /* list.h */; };
|
||||
E138A9780C04D88F00C5426C /* ProgressGradients.m in Sources */ = {isa = PBXBuildFile; fileRef = E138A9760C04D88F00C5426C /* ProgressGradients.m */; };
|
||||
|
@ -1192,6 +1194,8 @@
|
|||
BEFC1E1D0C07861A00B0BB3C /* completion.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = completion.c; path = libtransmission/completion.c; sourceTree = "<group>"; };
|
||||
BEFC1E1E0C07861A00B0BB3C /* clients.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = clients.h; path = libtransmission/clients.h; sourceTree = "<group>"; };
|
||||
BEFC1E1F0C07861A00B0BB3C /* clients.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = clients.c; path = libtransmission/clients.c; sourceTree = "<group>"; };
|
||||
C1077A4A183EB29600634C22 /* error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = error.c; path = libtransmission/error.c; sourceTree = "<group>"; };
|
||||
C1077A4B183EB29600634C22 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = error.h; path = libtransmission/error.h; sourceTree = "<group>"; };
|
||||
D4AF3B2D0C41F7A500D46B6B /* list.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = list.c; path = libtransmission/list.c; sourceTree = "<group>"; };
|
||||
D4AF3B2E0C41F7A500D46B6B /* list.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = list.h; path = libtransmission/list.h; sourceTree = "<group>"; };
|
||||
E138A9750C04D88F00C5426C /* ProgressGradients.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ProgressGradients.h; path = macosx/ProgressGradients.h; sourceTree = "<group>"; };
|
||||
|
@ -1646,6 +1650,8 @@
|
|||
4D1838DC09DEC04A0047D688 /* libtransmission */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C1077A4A183EB29600634C22 /* error.c */,
|
||||
C1077A4B183EB29600634C22 /* error.h */,
|
||||
4D80185710BBC0B0008A4AF2 /* magnet.c */,
|
||||
4D80185810BBC0B0008A4AF2 /* magnet.h */,
|
||||
4D8017E810BBC073008A4AF2 /* torrent-magnet.c */,
|
||||
|
@ -2083,6 +2089,7 @@
|
|||
A220EC5C118C8A060022B4BE /* tr-lpd.h in Headers */,
|
||||
A23547E311CD0B090046EAE6 /* cache.h in Headers */,
|
||||
A284214512DA663E00FBDDBB /* tr-udp.h in Headers */,
|
||||
C1077A4F183EB29600634C22 /* error.h in Headers */,
|
||||
A2679295130E00A000CB7464 /* tr-utp.h in Headers */,
|
||||
A23F29A1132A447400E9A83B /* announcer-common.h in Headers */,
|
||||
A2EE726F14DCCC950093C99A /* natpmp_local.h in Headers */,
|
||||
|
@ -2657,6 +2664,7 @@
|
|||
BEFC1E3C0C07861A00B0BB3C /* platform.c in Sources */,
|
||||
BEFC1E460C07861A00B0BB3C /* net.c in Sources */,
|
||||
BEFC1E480C07861A00B0BB3C /* natpmp.c in Sources */,
|
||||
C1077A4E183EB29600634C22 /* error.c in Sources */,
|
||||
BEFC1E4A0C07861A00B0BB3C /* metainfo.c in Sources */,
|
||||
BEFC1E4F0C07861A00B0BB3C /* inout.c in Sources */,
|
||||
BEFC1E530C07861A00B0BB3C /* fdlimit.c in Sources */,
|
||||
|
|
|
@ -28,6 +28,7 @@ libtransmission_a_SOURCES = \
|
|||
completion.c \
|
||||
ConvertUTF.c \
|
||||
crypto.c \
|
||||
error.c \
|
||||
fdlimit.c \
|
||||
handshake.c \
|
||||
history.c \
|
||||
|
@ -82,6 +83,7 @@ noinst_HEADERS = \
|
|||
ConvertUTF.h \
|
||||
crypto.h \
|
||||
completion.h \
|
||||
error.h \
|
||||
fdlimit.h \
|
||||
handshake.h \
|
||||
history.h \
|
||||
|
@ -133,6 +135,7 @@ TESTS = \
|
|||
blocklist-test \
|
||||
clients-test \
|
||||
crypto-test \
|
||||
error-test \
|
||||
history-test \
|
||||
json-test \
|
||||
magnet-test \
|
||||
|
@ -184,6 +187,10 @@ crypto_test_SOURCES = crypto-test.c $(TEST_SOURCES)
|
|||
crypto_test_LDADD = ${apps_ldadd}
|
||||
crypto_test_LDFLAGS = ${apps_ldflags}
|
||||
|
||||
error_test_SOURCES = error-test.c $(TEST_SOURCES)
|
||||
error_test_LDADD = ${apps_ldadd}
|
||||
error_test_LDFLAGS = ${apps_ldflags}
|
||||
|
||||
history_test_SOURCES = history-test.c $(TEST_SOURCES)
|
||||
history_test_LDADD = ${apps_ldadd}
|
||||
history_test_LDFLAGS = ${apps_ldflags}
|
||||
|
|
95
libtransmission/error-test.c
Normal file
95
libtransmission/error-test.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* This file Copyright (C) 2013-2014 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "transmission.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "libtransmission-test.h"
|
||||
|
||||
static int
|
||||
test_error_set (void)
|
||||
{
|
||||
tr_error * err = NULL;
|
||||
|
||||
#if 0
|
||||
|
||||
tr_error_prefix (&err, "error: ");
|
||||
check (err == NULL);
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
tr_error_set (&err, 1, "error: %s (%d)", "oops", 2);
|
||||
check (err != NULL);
|
||||
check_int_eq (1, err->code);
|
||||
check_streq ("error: oops (2)", err->message);
|
||||
tr_error_clear (&err);
|
||||
check (err == NULL);
|
||||
|
||||
tr_error_set_literal (&err, 2, "oops");
|
||||
check (err != NULL);
|
||||
check_int_eq (2, err->code);
|
||||
check_streq ("oops", err->message);
|
||||
|
||||
#if 0
|
||||
|
||||
tr_error_prefix (&err, "error: ");
|
||||
check (err != NULL);
|
||||
check_int_eq (2, err->code);
|
||||
check_streq ("error: oops", err->message);
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
tr_error_free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_error_propagate (void)
|
||||
{
|
||||
tr_error * err = NULL;
|
||||
tr_error * err2 = NULL;
|
||||
|
||||
tr_error_set_literal (&err, 1, "oops");
|
||||
check (err != NULL);
|
||||
check_int_eq (1, err->code);
|
||||
check_streq ("oops", err->message);
|
||||
|
||||
tr_error_propagate (&err2, &err);
|
||||
check (err2 != NULL);
|
||||
check_int_eq (1, err2->code);
|
||||
check_streq ("oops", err2->message);
|
||||
check (err == NULL);
|
||||
|
||||
#if 0
|
||||
|
||||
tr_error_propagate_prefixed (&err, &err2, "error: ");
|
||||
check (err != NULL);
|
||||
check_int_eq (1, err->code);
|
||||
check_streq ("error: oops", err->message);
|
||||
check (err2 == NULL);
|
||||
|
||||
tr_error_propagate (NULL, &err);
|
||||
check (err == NULL);
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
tr_error_free (err2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
const testFunc tests[] = { test_error_set,
|
||||
test_error_propagate };
|
||||
|
||||
return runTests (tests, NUM_TESTS (tests));
|
||||
}
|
198
libtransmission/error.c
Normal file
198
libtransmission/error.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* This file Copyright (C) 2013-2014 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "transmission.h"
|
||||
#include "error.h"
|
||||
#include "utils.h"
|
||||
|
||||
tr_error *
|
||||
tr_error_new (int code,
|
||||
const char * message_format,
|
||||
...)
|
||||
{
|
||||
tr_error * error;
|
||||
va_list args;
|
||||
|
||||
assert (message_format != NULL);
|
||||
|
||||
va_start (args, message_format);
|
||||
error = tr_error_new_valist (code, message_format, args);
|
||||
va_end (args);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
tr_error *
|
||||
tr_error_new_literal (int code,
|
||||
const char * message)
|
||||
{
|
||||
tr_error * error;
|
||||
|
||||
assert (message != NULL);
|
||||
|
||||
error = tr_new (tr_error, 1);
|
||||
error->code = code;
|
||||
error->message = tr_strdup (message);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
tr_error *
|
||||
tr_error_new_valist (int code,
|
||||
const char * message_format,
|
||||
va_list args)
|
||||
{
|
||||
tr_error * error;
|
||||
|
||||
assert (message_format != NULL);
|
||||
|
||||
error = tr_new (tr_error, 1);
|
||||
error->code = code;
|
||||
error->message = tr_strdup_vprintf (message_format, args);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
tr_error_free (tr_error * error)
|
||||
{
|
||||
if (error == NULL)
|
||||
return;
|
||||
|
||||
tr_free (error->message);
|
||||
tr_free (error);
|
||||
}
|
||||
|
||||
void
|
||||
tr_error_set (tr_error ** error,
|
||||
int code,
|
||||
const char * message_format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (error == NULL)
|
||||
return;
|
||||
|
||||
assert (*error == NULL);
|
||||
assert (message_format != NULL);
|
||||
|
||||
va_start (args, message_format);
|
||||
*error = tr_error_new_valist (code, message_format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
tr_error_set_literal (tr_error ** error,
|
||||
int code,
|
||||
const char * message)
|
||||
{
|
||||
if (error == NULL)
|
||||
return;
|
||||
|
||||
assert (*error == NULL);
|
||||
assert (message != NULL);
|
||||
|
||||
*error = tr_error_new_literal (code, message);
|
||||
}
|
||||
|
||||
void
|
||||
tr_error_propagate (tr_error ** new_error,
|
||||
tr_error ** old_error)
|
||||
{
|
||||
assert (old_error != NULL);
|
||||
assert (*old_error != NULL);
|
||||
|
||||
if (new_error != NULL)
|
||||
{
|
||||
assert (*new_error == NULL);
|
||||
|
||||
*new_error = *old_error;
|
||||
*old_error = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_error_clear (old_error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_error_clear (tr_error ** error)
|
||||
{
|
||||
if (error == NULL)
|
||||
return;
|
||||
|
||||
tr_error_free (*error);
|
||||
|
||||
*error = NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void
|
||||
error_prefix_valist (tr_error ** error,
|
||||
const char * prefix_format,
|
||||
va_list args)
|
||||
{
|
||||
char * prefix;
|
||||
char * new_message;
|
||||
|
||||
assert (error != NULL);
|
||||
assert (*error != NULL);
|
||||
assert (prefix_format != NULL);
|
||||
|
||||
prefix = tr_strdup_vprintf (prefix_format, args);
|
||||
|
||||
new_message = tr_strdup_printf ("%s%s", prefix, (*error)->message);
|
||||
tr_free ((*error)->message);
|
||||
(*error)->message = new_message;
|
||||
|
||||
tr_free (prefix);
|
||||
}
|
||||
|
||||
void
|
||||
tr_error_prefix (tr_error ** error,
|
||||
const char * prefix_format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
assert (prefix_format != NULL);
|
||||
|
||||
if (error == NULL || *error == NULL)
|
||||
return;
|
||||
|
||||
va_start (args, prefix_format);
|
||||
error_prefix_valist (error, prefix_format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
tr_error_propagate_prefixed (tr_error ** new_error,
|
||||
tr_error ** old_error,
|
||||
const char * prefix_format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
assert (prefix_format != NULL);
|
||||
|
||||
tr_error_propagate (new_error, old_error);
|
||||
|
||||
if (new_error == NULL)
|
||||
return;
|
||||
|
||||
va_start (args, prefix_format);
|
||||
error_prefix_valist (new_error, prefix_format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
178
libtransmission/error.h
Normal file
178
libtransmission/error.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* This file Copyright (C) 2013-2014 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef TR_ERROR_H
|
||||
#define TR_ERROR_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef TR_GNUC_PRINTF
|
||||
#ifdef __GNUC__
|
||||
#define TR_GNUC_PRINTF(fmt, args) __attribute__ ((format (printf, fmt, args)))
|
||||
#else
|
||||
#define TR_GNUC_PRINTF(fmt, args)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup error Error reporting
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Structure holding error information. */
|
||||
typedef struct tr_error
|
||||
{
|
||||
/** @brief Error code, platform-specific */
|
||||
int code;
|
||||
/** @brief Error message */
|
||||
char * message;
|
||||
}
|
||||
tr_error;
|
||||
|
||||
/**
|
||||
* @brief Create new error object using `printf`-style formatting.
|
||||
*
|
||||
* @param[in] code Error code (platform-specific).
|
||||
* @param[in] message_format Error message format string.
|
||||
* @param[in] ... Format arguments.
|
||||
*
|
||||
* @return Newly allocated error object on success, `NULL` otherwise.
|
||||
*/
|
||||
tr_error * tr_error_new (int code,
|
||||
const char * message_format,
|
||||
...) TR_GNUC_PRINTF (2, 3);
|
||||
|
||||
/**
|
||||
* @brief Create new error object using literal error message.
|
||||
*
|
||||
* @param[in] code Error code (platform-specific).
|
||||
* @param[in] message Error message.
|
||||
*
|
||||
* @return Newly allocated error object on success, `NULL` otherwise.
|
||||
*/
|
||||
tr_error * tr_error_new_literal (int code,
|
||||
const char * message);
|
||||
|
||||
/**
|
||||
* @brief Create new error object using `vprintf`-style formatting.
|
||||
*
|
||||
* @param[in] code Error code (platform-specific).
|
||||
* @param[in] message_format Error message format string.
|
||||
* @param[in] args Format arguments.
|
||||
*
|
||||
* @return Newly allocated error object on success, `NULL` otherwise.
|
||||
*/
|
||||
tr_error * tr_error_new_valist (int code,
|
||||
const char * message_format,
|
||||
va_list args);
|
||||
|
||||
/**
|
||||
* @brief Free memory used by error object.
|
||||
*
|
||||
* @param[in] error Error object to be freed.
|
||||
*/
|
||||
void tr_error_free (tr_error * error);
|
||||
|
||||
/**
|
||||
* @brief Create and set new error object using `printf`-style formatting.
|
||||
*
|
||||
* If passed pointer to error object is `NULL`, do nothing.
|
||||
*
|
||||
* @param[in,out] error Pointer to error object to be set.
|
||||
* @param[in] code Error code (platform-specific).
|
||||
* @param[in] message_format Error message format string.
|
||||
* @param[in] ... Format arguments.
|
||||
*/
|
||||
void tr_error_set (tr_error ** error,
|
||||
int code,
|
||||
const char * message_format,
|
||||
...) TR_GNUC_PRINTF (3, 4);
|
||||
|
||||
/**
|
||||
* @brief Create and set new error object using literal error message.
|
||||
*
|
||||
* If passed pointer to error object is `NULL`, do nothing.
|
||||
*
|
||||
* @param[in,out] error Pointer to error object to be set.
|
||||
* @param[in] code Error code (platform-specific).
|
||||
* @param[in] message Error message.
|
||||
*/
|
||||
void tr_error_set_literal (tr_error ** error,
|
||||
int code,
|
||||
const char * message);
|
||||
|
||||
/**
|
||||
* @brief Propagate existing error object upwards.
|
||||
*
|
||||
* If passed pointer to new error object is not `NULL`, copy old error object to
|
||||
* new error object and free old error object. Otherwise, just free old error
|
||||
* object.
|
||||
*
|
||||
* @param[in,out] new_error Pointer to error object to be set.
|
||||
* @param[in,out] old_error Error object to be propagated. Cleared on return.
|
||||
*/
|
||||
void tr_error_propagate (tr_error ** new_error,
|
||||
tr_error ** old_error);
|
||||
|
||||
/**
|
||||
* @brief Clear error object.
|
||||
*
|
||||
* Free error object being pointed and set pointer to `NULL`. If passed pointer
|
||||
* is `NULL`, do nothing.
|
||||
*
|
||||
* @param[in,out] error Pointer to error object to be cleared.
|
||||
*/
|
||||
void tr_error_clear (tr_error ** error);
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
* @brief Prefix message of exising error object.
|
||||
*
|
||||
* If passed pointer to error object is not `NULL`, prefix its message with
|
||||
* `printf`-style formatted text. Otherwise, do nothing.
|
||||
*
|
||||
* @param[in,out] error Pointer to error object to be set.
|
||||
* @param[in] prefix_format Prefix format string.
|
||||
* @param[in] ... Format arguments.
|
||||
*/
|
||||
void tr_error_prefix (tr_error ** error,
|
||||
const char * prefix_format,
|
||||
...) TR_GNUC_PRINTF (2, 3);
|
||||
|
||||
/**
|
||||
* @brief Prefix message and propagate existing error object upwards.
|
||||
*
|
||||
* If passed pointer to new error object is not `NULL`, copy old error object to
|
||||
* new error object, prefix its message with `printf`-style formatted text, and
|
||||
* free old error object. Otherwise, just free old error object.
|
||||
*
|
||||
* @param[in,out] new_error Pointer to error object to be set.
|
||||
* @param[in,out] old_error Error object to be propagated. Cleared on return.
|
||||
* @param[in] prefix_format Prefix format string.
|
||||
* @param[in] ... Format arguments.
|
||||
*/
|
||||
void tr_error_propagate_prefixed (tr_error ** new_error,
|
||||
tr_error ** old_error,
|
||||
const char * prefix_format,
|
||||
...) TR_GNUC_PRINTF (3, 4);
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -421,6 +421,63 @@ test_cryptoRand (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
test_strdup_printf_valist (const char * fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char * ret;
|
||||
|
||||
va_start (args, fmt);
|
||||
ret = tr_strdup_vprintf (fmt, args);
|
||||
va_end (args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
test_strdup_printf (void)
|
||||
{
|
||||
char * s, * s2, * s3;
|
||||
|
||||
s = tr_strdup_printf ("%s", "test");
|
||||
check_streq ("test", s);
|
||||
tr_free (s);
|
||||
|
||||
s = tr_strdup_printf ("%d %s %c %u", -1, "0", '1', 2);
|
||||
check_streq ("-1 0 1 2", s);
|
||||
tr_free (s);
|
||||
|
||||
s3 = tr_malloc0 (4098);
|
||||
memset (s3, '-', 4097);
|
||||
s3[2047] = 't';
|
||||
s3[2048] = 'e';
|
||||
s3[2049] = 's';
|
||||
s3[2050] = 't';
|
||||
|
||||
s2 = tr_malloc0 (4096);
|
||||
memset (s2, '-', 4095);
|
||||
s2[2047] = '%';
|
||||
s2[2048] = 's';
|
||||
|
||||
s = tr_strdup_printf (s2, "test");
|
||||
check_streq (s3, s);
|
||||
tr_free (s);
|
||||
|
||||
tr_free (s2);
|
||||
|
||||
s = tr_strdup_printf ("%s", s3);
|
||||
check_streq (s3, s);
|
||||
tr_free (s);
|
||||
|
||||
tr_free (s3);
|
||||
|
||||
s = test_strdup_printf_valist ("\n-%s-%s-%s-\n", "\r", "\t", "\b");
|
||||
check_streq ("\n-\r-\t-\b-\n", s);
|
||||
tr_free (s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
@ -434,6 +491,7 @@ main (void)
|
|||
test_memmem,
|
||||
test_numbers,
|
||||
test_strip_positional_args,
|
||||
test_strdup_printf,
|
||||
test_strstrip,
|
||||
test_truncd,
|
||||
test_url,
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <float.h> /* DBL_EPSILON */
|
||||
#include <locale.h> /* localeconv () */
|
||||
#include <math.h> /* pow (), fabs (), floor () */
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* strerror (), memset (), memmem () */
|
||||
|
@ -602,28 +601,23 @@ tr_strdup_printf (const char * fmt, ...)
|
|||
{
|
||||
va_list ap;
|
||||
char * ret;
|
||||
size_t len;
|
||||
char statbuf[2048];
|
||||
|
||||
va_start (ap, fmt);
|
||||
len = evutil_vsnprintf (statbuf, sizeof (statbuf), fmt, ap);
|
||||
ret = tr_strdup_vprintf (fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (len < sizeof (statbuf))
|
||||
{
|
||||
ret = tr_strndup (statbuf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = tr_new (char, len + 1);
|
||||
va_start (ap, fmt);
|
||||
evutil_vsnprintf (ret, len + 1, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
tr_strdup_vprintf (const char * fmt,
|
||||
va_list args)
|
||||
{
|
||||
struct evbuffer * buf = evbuffer_new ();
|
||||
evbuffer_add_vprintf (buf, fmt, args);
|
||||
return evbuffer_free_to_str (buf);
|
||||
}
|
||||
|
||||
const char*
|
||||
tr_strerror (int i)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define TR_UTILS_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <time.h> /* time_t */
|
||||
|
||||
|
@ -267,6 +268,8 @@ void tr_quickfindFirstK (void * base, size_t nmemb, size_t size,
|
|||
*/
|
||||
char* tr_strdup_printf (const char * fmt, ...) TR_GNUC_PRINTF (1, 2)
|
||||
TR_GNUC_MALLOC;
|
||||
char * tr_strdup_vprintf (const char * fmt,
|
||||
va_list args) TR_GNUC_MALLOC;
|
||||
|
||||
/**
|
||||
* @brief Translate a block of bytes into base64
|
||||
|
|
Loading…
Reference in a new issue