Move the snprintf functions to the platform module

Moving the implementation of the snprintf wrapper functions to the
platform module allows to re-use the same implementation throughout the
entire codebase.
This commit is contained in:
Jef Driesen 2023-01-03 21:08:21 +01:00
parent fca64faa3c
commit 187f8d625b
9 changed files with 74 additions and 69 deletions

View File

@ -24,7 +24,6 @@
#endif
#include <stdlib.h> // malloc, free
#include <stdio.h>
#include "socket.h"
@ -231,7 +230,7 @@ dc_bluetooth_addr2str(dc_bluetooth_address_t address, char *str, size_t size)
if (str == NULL || size < DC_BLUETOOTH_SIZE)
return NULL;
int n = snprintf(str, size, "%02X:%02X:%02X:%02X:%02X:%02X",
int n = dc_platform_snprintf(str, size, "%02X:%02X:%02X:%02X:%02X:%02X",
(unsigned char)((address >> 40) & 0xFF),
(unsigned char)((address >> 32) & 0xFF),
(unsigned char)((address >> 24) & 0xFF),

View File

@ -28,6 +28,8 @@
#include <libdivecomputer/context.h>
#include "platform.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@ -40,12 +42,6 @@ extern "C" {
#define FUNCTION __FUNCTION__
#endif
#if defined(__GNUC__)
#define ATTR_FORMAT_PRINTF(a,b) __attribute__((format(printf, a, b)))
#else
#define ATTR_FORMAT_PRINTF(a,b)
#endif
#ifdef ENABLE_LOGGING
#define HEXDUMP(context, loglevel, prefix, data, size) dc_context_hexdump (context, loglevel, __FILE__, __LINE__, FUNCTION, prefix, data, size)
#define SYSERROR(context, errcode) dc_context_syserror (context, DC_LOGLEVEL_ERROR, __FILE__, __LINE__, FUNCTION, errcode)
@ -63,7 +59,7 @@ extern "C" {
#endif
dc_status_t
dc_context_log (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *format, ...) ATTR_FORMAT_PRINTF(6, 7);
dc_context_log (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *format, ...) DC_ATTR_FORMAT_PRINTF(6, 7);
dc_status_t
dc_context_syserror (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, int errcode);

View File

@ -25,7 +25,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
@ -36,6 +35,7 @@
#endif
#include "context-private.h"
#include "platform.h"
#include "timer.h"
struct dc_context_t {
@ -49,55 +49,6 @@ struct dc_context_t {
};
#ifdef ENABLE_LOGGING
/*
* A wrapper for the vsnprintf function, which will always null terminate the
* string and returns a negative value if the destination buffer is too small.
*/
static int
l_vsnprintf (char *str, size_t size, const char *format, va_list ap)
{
int n;
if (size == 0)
return -1;
#ifdef _MSC_VER
/*
* The non-standard vsnprintf implementation provided by MSVC doesn't null
* terminate the string and returns a negative value if the destination
* buffer is too small.
*/
n = _vsnprintf (str, size - 1, format, ap);
if (n == size - 1 || n < 0)
str[size - 1] = 0;
#else
/*
* The C99 vsnprintf function will always null terminate the string. If the
* destination buffer is too small, the return value is the number of
* characters that would have been written if the buffer had been large
* enough.
*/
n = vsnprintf (str, size, format, ap);
if (n >= 0 && (size_t) n >= size)
n = -1;
#endif
return n;
}
static int
l_snprintf (char *str, size_t size, const char *format, ...)
{
va_list ap;
int n;
va_start (ap, format);
n = l_vsnprintf (str, size, format, ap);
va_end (ap);
return n;
}
static int
l_hexdump (char *str, size_t size, const unsigned char data[], size_t n)
{
@ -244,7 +195,7 @@ dc_context_log (dc_context_t *context, dc_loglevel_t loglevel, const char *file,
return DC_STATUS_SUCCESS;
va_start (ap, format);
l_vsnprintf (context->msg, sizeof (context->msg), format, ap);
dc_platform_vsnprintf (context->msg, sizeof (context->msg), format, ap);
va_end (ap);
context->logfunc (context, loglevel, file, line, function, context->msg, context->userdata);
@ -310,7 +261,7 @@ dc_context_hexdump (dc_context_t *context, dc_loglevel_t loglevel, const char *f
if (context->logfunc == NULL)
return DC_STATUS_SUCCESS;
n = l_snprintf (context->msg, sizeof (context->msg), "%s: size=%u, data=", prefix, size);
n = dc_platform_snprintf (context->msg, sizeof (context->msg), "%s: size=%u, data=", prefix, size);
if (n >= 0) {
n = l_hexdump (context->msg + n, sizeof (context->msg) - n, data, size);

View File

@ -1447,7 +1447,7 @@ hw_ostc3_device_fwupdate3 (dc_device_t *abstract, const char *filename)
for (unsigned int len = 0; len < SZ_FIRMWARE; len += SZ_FIRMWARE_BLOCK) {
char status[SZ_DISPLAY + 1]; // Status message on the display
snprintf (status, sizeof(status), " Uploading %2d%%", (100 * len) / SZ_FIRMWARE);
dc_platform_snprintf (status, sizeof(status), " Uploading %2d%%", (100 * len) / SZ_FIRMWARE);
hw_ostc3_device_display (abstract, status);
rc = hw_ostc3_firmware_block_write (device, FIRMWARE_AREA + len, firmware->data + len, SZ_FIRMWARE_BLOCK);
@ -1466,7 +1466,7 @@ hw_ostc3_device_fwupdate3 (dc_device_t *abstract, const char *filename)
for (unsigned int len = 0; len < SZ_FIRMWARE; len += SZ_FIRMWARE_BLOCK) {
unsigned char block[SZ_FIRMWARE_BLOCK];
char status[SZ_DISPLAY + 1]; // Status message on the display
snprintf (status, sizeof(status), " Verifying %2d%%", (100 * len) / SZ_FIRMWARE);
dc_platform_snprintf (status, sizeof(status), " Verifying %2d%%", (100 * len) / SZ_FIRMWARE);
hw_ostc3_device_display (abstract, status);
rc = hw_ostc3_firmware_block_read (device, FIRMWARE_AREA + len, block, sizeof (block));

View File

@ -24,7 +24,6 @@
#endif
#include <stdlib.h> // malloc, free
#include <stdio.h> // snprintf
#include <string.h>
#include "socket.h"
@ -314,7 +313,7 @@ dc_irda_open (dc_iostream_t **out, dc_context_t *context, unsigned int address,
peer.irdaDeviceID[1] = (address >> 8) & 0xFF;
peer.irdaDeviceID[2] = (address >> 16) & 0xFF;
peer.irdaDeviceID[3] = (address >> 24) & 0xFF;
snprintf (peer.irdaServiceName, sizeof(peer.irdaServiceName), "LSAP-SEL%u", lsap);
dc_platform_snprintf (peer.irdaServiceName, sizeof(peer.irdaServiceName), "LSAP-SEL%u", lsap);
#else
struct sockaddr_irda peer;
peer.sir_family = AF_IRDA;

View File

@ -28,6 +28,8 @@
#include <errno.h>
#endif
#include <stdio.h>
#include "platform.h"
int
@ -49,3 +51,48 @@ dc_platform_sleep (unsigned int milliseconds)
return 0;
}
int
dc_platform_vsnprintf (char *str, size_t size, const char *format, va_list ap)
{
int n = 0;
if (size == 0)
return -1;
#ifdef _MSC_VER
/*
* The non-standard vsnprintf implementation provided by MSVC doesn't null
* terminate the string and returns a negative value if the destination
* buffer is too small.
*/
n = _vsnprintf (str, size - 1, format, ap);
if (n == size - 1 || n < 0)
str[size - 1] = 0;
#else
/*
* The C99 vsnprintf function will always null terminate the string. If the
* destination buffer is too small, the return value is the number of
* characters that would have been written if the buffer had been large
* enough.
*/
n = vsnprintf (str, size, format, ap);
if (n >= 0 && (size_t) n >= size)
n = -1;
#endif
return n;
}
int
dc_platform_snprintf (char *str, size_t size, const char *format, ...)
{
va_list ap;
int n = 0;
va_start (ap, format);
n = dc_platform_vsnprintf (str, size, format, ap);
va_end (ap);
return n;
}

View File

@ -22,10 +22,18 @@
#ifndef DC_PLATFORM_H
#define DC_PLATFORM_H
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#if defined(__GNUC__)
#define DC_ATTR_FORMAT_PRINTF(a,b) __attribute__((format(printf, a, b)))
#else
#define DC_ATTR_FORMAT_PRINTF(a,b)
#endif
#ifdef _WIN32
#define DC_PRINTF_SIZE "%Iu"
#else
@ -33,7 +41,6 @@ extern "C" {
#endif
#ifdef _MSC_VER
#define snprintf _snprintf
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#if _MSC_VER < 1800
@ -47,6 +54,13 @@ extern "C" {
int dc_platform_sleep(unsigned int milliseconds);
/*
* A wrapper for the vsnprintf function, which will always null terminate the
* string and returns a negative value if the destination buffer is too small.
*/
int dc_platform_snprintf (char *str, size_t size, const char *format, ...) DC_ATTR_FORMAT_PRINTF(3, 4);
int dc_platform_vsnprintf (char *str, size_t size, const char *format, va_list ap) DC_ATTR_FORMAT_PRINTF(3, 0);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -37,7 +37,6 @@
#ifdef HAVE_IOKIT_SERIAL_IOSS_H
#include <IOKit/serial/ioss.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <fnmatch.h>
@ -226,7 +225,7 @@ dc_serial_iterator_next (dc_iterator_t *abstract, void *out)
continue;
char filename[sizeof(device->name)];
int n = snprintf (filename, sizeof (filename), "%s/%s", DIRNAME, ep->d_name);
int n = dc_platform_snprintf (filename, sizeof (filename), "%s/%s", DIRNAME, ep->d_name);
if (n < 0 || (size_t) n >= sizeof (filename)) {
return DC_STATUS_NOMEMORY;
}

View File

@ -897,7 +897,7 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac
break;
}
len = snprintf(pathname, sizeof(pathname), "%s/%s", dive_directory, de->name);
len = dc_platform_snprintf(pathname, sizeof(pathname), "%s/%s", dive_directory, de->name);
if (len < 0 || (unsigned int) len >= sizeof(pathname)) {
dc_status_set_error(&status, DC_STATUS_PROTOCOL);
break;