mike.dld's portability improvements to libtransmission, pt 1

This commit is contained in:
Jordan Lee 2014-06-23 02:38:53 +00:00
parent 650091aed7
commit 92daae473e
8 changed files with 557 additions and 16 deletions

View File

@ -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 */,

View File

@ -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}

View 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
View 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
View 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

View File

@ -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,

View File

@ -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)
{

View File

@ -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