Merge pull request #13548 from evva-sfw/enhance-minimal-printf

Add width modifier and prepending zeros for hexadecimal output and decimal precision for floating point
pull/13977/head
Martin Kojtal 2020-12-10 09:14:59 +00:00 committed by GitHub
commit c06fcaf5c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 526 additions and 158 deletions

View File

@ -3,7 +3,7 @@
Library supports both printf and snprintf in around 1300 bytes of flash. Library supports both printf and snprintf in around 1300 bytes of flash.
Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored. Prints directly to stdio/UART without using malloc. Width size and prepending zero modifiers are supported. All other flags are ignored.
There is no error handling if a writing error occurs. There is no error handling if a writing error occurs.
Supports: Supports:
@ -12,10 +12,10 @@ Supports:
* %u: unsigned integer [h, hh, (none), l, ll, z, j, t]. * %u: unsigned integer [h, hh, (none), l, ll, z, j, t].
* %x: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., ff). * %x: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., ff).
* %X: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., FF). * %X: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., FF).
* %f: floating point (disabled by default). * %f: floating point (disabled by default). Precision modifier is supported (e.g. %.5f).
* %F: floating point (disabled by default, treated as %f). * %F: floating point (disabled by default, treated as %f). Precision modifier is supported (e.g. %.5F).
* %g: floating point (disabled by default, treated as %f). * %g: floating point (disabled by default, treated as %f). Precision modifier is supported (e.g. %.5g).
* %G: floating point (disabled by default, treated as %f). * %G: floating point (disabled by default, treated as %f). Precision modifier is supported (e.g. %.5G).
* %c: character. * %c: character.
* %s: string. * %s: string.
* %p: pointer (e.g. 0x00123456). * %p: pointer (e.g. 0x00123456).

View File

@ -21,6 +21,7 @@
#include <limits.h> #include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <string.h>
#if !TARGET_LIKE_MBED #if !TARGET_LIKE_MBED
/* Linux implementation is for debug only */ /* Linux implementation is for debug only */
@ -86,12 +87,21 @@ typedef enum {
LENGTH_LL = 0x82 LENGTH_LL = 0x82
} length_t; } length_t;
/**
* Enum for integer printing type
*/
typedef enum {
INT_UNSIGNED,
INT_SIGNED,
HEX_LOWER,
HEX_UPPER,
ZERO_NEGATIVE /* special case when printing integer part of double values where it is 0 and the value is negative */
} integer_type_t;
/** /**
* Prototypes * Prototypes
*/ */
static void mbed_minimal_formatted_string_signed(char *buffer, size_t length, int *result, MBED_SIGNED_STORAGE value, FILE *stream); static void mbed_minimal_formatted_string_integer(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, integer_type_t type, int width_size, bool prepend_zeros, FILE *stream);
static void mbed_minimal_formatted_string_unsigned(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream);
static void mbed_minimal_formatted_string_hexadecimal(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream, bool upper);
static void mbed_minimal_formatted_string_void_pointer(char *buffer, size_t length, int *result, const void *value, FILE *stream); static void mbed_minimal_formatted_string_void_pointer(char *buffer, size_t length, int *result, const void *value, FILE *stream);
static void mbed_minimal_formatted_string_string(char *buffer, size_t length, int *result, const char *string, size_t precision, FILE *stream); static void mbed_minimal_formatted_string_string(char *buffer, size_t length, int *result, const char *string, size_t precision, FILE *stream);
@ -130,105 +140,96 @@ static void mbed_minimal_putchar(char *buffer, size_t length, int *result, char
} }
/** /**
* @brief Print signed integer. * @brief Print integer in signed, unsigned or hexadecimal format.
* *
* @param buffer The buffer to store output (NULL for stdout). * @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer. * @param[in] length The length of the buffer.
* @param result The current output location. * @param result The current output location.
* @param[in] value The value to be printed. * @param[in] value The value to be printed.
* @param type The type of integer format that shall be printed (signed, unsigend or hexadecimal)
* @param width_size The width modifier.
* @param prepend_zeros Flag to prepends zeros when the width_size is greater than 0
*/ */
static void mbed_minimal_formatted_string_signed(char *buffer, size_t length, int *result, MBED_SIGNED_STORAGE value, FILE *stream) static void mbed_minimal_formatted_string_integer(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, integer_type_t type, int width_size, bool prepend_zeros, FILE *stream)
{ {
MBED_UNSIGNED_STORAGE new_value = 0; /* allocate 3 digits per byte */
char scratch[sizeof(MBED_UNSIGNED_STORAGE) * 3] = { 0 };
/* if value is negative print sign and treat as positive number */ int index = 0;
if (value < 0) {
/* write sign */
mbed_minimal_putchar(buffer, length, result, '-', stream);
/* get absolute value using two's complement */ bool negative_value = false;
new_value = ~((MBED_UNSIGNED_STORAGE) value) + 1;
} else { const char filler = prepend_zeros ? '0' : ' ';
new_value = value;
if (type == INT_SIGNED) {
if ((MBED_SIGNED_STORAGE) value < 0) {
/* get absolute value using two's complement */
value = ~value + 1;
negative_value = true;
}
} else if (type == ZERO_NEGATIVE) {
negative_value = true;
} }
/* use unsigned long int function */
mbed_minimal_formatted_string_unsigned(buffer, length, result, new_value, stream);
}
/**
* @brief Print unsigned integer.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The value to be printed.
*/
static void mbed_minimal_formatted_string_unsigned(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream)
{
/* treat 0 as a corner case */
if (value == 0) { if (value == 0) {
mbed_minimal_putchar(buffer, length, result, '0', stream); scratch[index] = '0';
index++;
} else { } else {
/* allocate 3 digits per byte */
char scratch[sizeof(MBED_UNSIGNED_STORAGE) * 3] = { 0 };
size_t index = 0;
/* write numbers in reverse order to scratch pad */ /* write numbers in reverse order to scratch pad */
for (; value > 0; index++) { for (; value > 0; index++) {
/* use '0' as base and add digit */ if (type == HEX_LOWER || type == HEX_UPPER) {
scratch[index] = '0' + (value % 10); /* get least significant byte */
const uint8_t output = value & 0x0F;
/* shift value one decimal position */ static const char int2hex_lower[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
value = value / 10; '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
} };
static const char int2hex_upper[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
/* write scratch pad to buffer or output */ if (type == HEX_LOWER) {
for (; index > 0; index--) { scratch[index] = int2hex_lower[output];
mbed_minimal_putchar(buffer, length, result, scratch[index - 1], stream); } else {
scratch[index] = int2hex_upper[output];
}
/* shift value one byte position */
value = value >> 4;
} else {
/* use '0' as base and add digit */
scratch[index] = '0' + (value % 10);
/* shift value one decimal position */
value = value / 10;
}
} }
} }
}
/** if (negative_value) {
* @brief Print hexadecimal. if (prepend_zeros) {
* mbed_minimal_putchar(buffer, length, result, '-', stream);
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The value to be printed.
* @param upper Flag to print the hexadecimal in upper or lower case.
*/
static void mbed_minimal_formatted_string_hexadecimal(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream, bool upper)
{
bool print_leading_zero = false;
for (int index = 7; index >= 0; index--) {
/* get most significant byte */
uint8_t output = value >> (8 * index);
/* only print leading zeros when set */
if (print_leading_zero || (output != 0) || (index == 0)) {
unsigned int nibble_one = (output >> 4);
unsigned int nibble_two = (output & 0x0F);
static const char int2hex_lower[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
static const char int2hex_upper[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
const char *int2hex = upper ? int2hex_upper : int2hex_lower;
if (print_leading_zero || nibble_one != 0) {
mbed_minimal_putchar(buffer, length, result, int2hex[nibble_one], stream);
}
mbed_minimal_putchar(buffer, length, result, int2hex[nibble_two], stream);
/* print zeroes after the first non-zero byte */
print_leading_zero = true;
} }
index++; // add one to index to count '-'
}
// print filler characters
if (width_size > index) {
for (int i = width_size; i > index; i--) {
mbed_minimal_putchar(buffer, length, result, filler, stream);
}
}
if (negative_value) {
if (!prepend_zeros) {
mbed_minimal_putchar(buffer, length, result, '-', stream);
}
index--; // Restore index to correct position
}
/* print absolute value of integer */
for (; index > 0; index--) {
mbed_minimal_putchar(buffer, length, result, scratch[index - 1], stream);
} }
} }
@ -247,69 +248,77 @@ static void mbed_minimal_formatted_string_void_pointer(char *buffer, size_t leng
mbed_minimal_putchar(buffer, length, result, 'x', stream); mbed_minimal_putchar(buffer, length, result, 'x', stream);
/* write rest as a regular hexadecimal number */ /* write rest as a regular hexadecimal number */
mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value, stream, true); mbed_minimal_formatted_string_integer(buffer, length, result, (ptrdiff_t) value, HEX_UPPER, 0, false, stream);
} }
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT #if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
/** /**
* @brief Write double. * @brief Write double.
* *
* @param buffer The buffer to store output (NULL for stdout). * @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer. * @param[in] length The length of the buffer.
* @param result The current output location. * @param result The current output location.
* @param[in] value The value to be printed. * @param[in] value The value to be printed.
* @param[in] dec_precision The decimal precision. If PRECISION_DEFAULT MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS is used.
* @param width_size The width modifier.
* @param prepend_zeros Flag to prepends zeros when the width_size is greater than 0
*/ */
static void mbed_minimal_formatted_string_double(char *buffer, size_t length, int *result, double value, FILE *stream) static void mbed_minimal_formatted_string_double(char *buffer, size_t length, int *result, double value, int dec_precision, int width_size, bool prepend_zeros, FILE *stream)
{ {
/* get integer part */ /* get integer part */
MBED_SIGNED_STORAGE integer = value; MBED_SIGNED_STORAGE integer = value;
/* write integer part */ if (dec_precision == PRECISION_DEFAULT) {
mbed_minimal_formatted_string_signed(buffer, length, result, integer, stream); dec_precision = MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS;
/* write decimal point */
mbed_minimal_putchar(buffer, length, result, '.', stream);
/* get decimal part */
double precision = 1.0;
for (size_t index = 0; index < MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS; index++) {
precision *= 10;
} }
value = (value - integer) * precision; if (dec_precision != 0) {
width_size -= dec_precision + 1; // decimal precision plus '.'
/* convert to unsigned integer */ if (width_size < 0) {
MBED_UNSIGNED_STORAGE decimal = 0; width_size = 0;
}
if (value < 0) {
MBED_SIGNED_STORAGE temp = value;
decimal = ~((MBED_UNSIGNED_STORAGE) temp) + 1;
} else { } else {
decimal = value; value = (value - integer) * 1.0;
if (!((value > -0.5) && (value < 0.5))) {
integer++;
}
} }
/* round up or down */ /* write integer part */
value -= decimal; if (integer == 0 && value < 0) {
mbed_minimal_formatted_string_integer(buffer, length, result, integer, ZERO_NEGATIVE, width_size, prepend_zeros, stream);
if (!((value > -0.5) && (value < 0.5))) { } else {
decimal++; mbed_minimal_formatted_string_integer(buffer, length, result, integer, INT_SIGNED, width_size, prepend_zeros, stream);
} }
/* convert precision to unsigned integer */ if (dec_precision != 0) {
MBED_UNSIGNED_STORAGE precision_in_uint = precision; /* write decimal point */
precision_in_uint /= 10; mbed_minimal_putchar(buffer, length, result, '.', stream);
/* ensure that leading zeros are printed if decimal equals 0 */ /* get decimal part */
MBED_UNSIGNED_STORAGE val = decimal ? decimal : decimal + 1; double precision = 1.0;
while (precision_in_uint > val) {
/* print leading zeros */ for (size_t index = 0; index < dec_precision; index++) {
mbed_minimal_putchar(buffer, length, result, '0', stream); precision *= 10;
precision_in_uint /= 10; }
/* convert to positive number */
if (value < 0.0) {
value *= -1.0;
}
MBED_UNSIGNED_STORAGE decimal = value;
/* round up or down */
value -= decimal;
if (!((value > -0.5) && (value < 0.5))) {
decimal++;
}
/* write decimal part */
mbed_minimal_formatted_string_integer(buffer, length, result, decimal, INT_UNSIGNED, dec_precision, true, stream);
} }
/* write decimal part */
mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal, stream);
} }
#endif #endif
@ -331,6 +340,26 @@ static void mbed_minimal_formatted_string_string(char *buffer, size_t length, in
} }
} }
/**
* @brief Parse a string to an integer value as long as there are numerical characters in the string
*
* @param[in] string The input string. Has to begin with a numerical character to parse
* @param[out] value The output value.
* @return size_t The number of numerical characters parsed
*/
static size_t parse_string_to_integer(const char *string, int *value)
{
size_t inner_index = 0;
while ((string[inner_index] >= '0') && (string[inner_index] <= '9')) {
*value = *value * 10 + (string[inner_index] - '0');
inner_index++;
}
return inner_index;
}
/** /**
* @brief Parse formatted string and invoke write handlers based on type. * @brief Parse formatted string and invoke write handlers based on type.
* *
@ -364,20 +393,22 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
size_t next_index = index + 1; size_t next_index = index + 1;
/************************************************************** /**************************************************************
* skip and ignore flags [-+(space)#0] * skip and ignore flags [-+(space)#]
*************************************************************/ *************************************************************/
if ((format[next_index] == '-') || if ((format[next_index] == '-') ||
(format[next_index] == '+') || (format[next_index] == '+') ||
(format[next_index] == ' ') || (format[next_index] == ' ') ||
(format[next_index] == '#') || (format[next_index] == '#')) {
(format[next_index] == '0')) {
/* skip to next character */ /* skip to next character */
next_index++; next_index++;
} }
/************************************************************** /**************************************************************
* skip and ignore width [(number)*] * look for width and prepending zeros [(number)], skip [*]
*************************************************************/ *************************************************************/
bool prepend_zeros = false;
int width_size = 0;
if (format[next_index] == '*') { if (format[next_index] == '*') {
/* skip to next character */ /* skip to next character */
next_index++; next_index++;
@ -385,11 +416,15 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
/* discard argument */ /* discard argument */
va_arg(arguments, MBED_SIGNED_NATIVE_TYPE); va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
} else { } else {
while ((format[next_index] >= '0') && if (format[next_index] == '0') {
(format[next_index] <= '9')) { prepend_zeros = true;
/* skip to next character */ do {
next_index++; next_index++;
} while (format[next_index] == '0');
} }
/* parse width modifier until not a decimal */
next_index += parse_string_to_integer(&format[next_index], &width_size);
} }
/************************************************************** /**************************************************************
@ -409,17 +444,7 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
precision = 0; precision = 0;
/* parse precision until not a decimal */ /* parse precision until not a decimal */
size_t inner_index = 0; next_index += parse_string_to_integer(&format[next_index], &precision);
while ((format[next_index + inner_index] >= '0') &&
(format[next_index + inner_index] <= '9')) {
precision = precision * 10 + (format[next_index + inner_index] - '0');
inner_index++;
}
/* move index forward to point at next character */
next_index += inner_index;
} }
/************************************************************** /**************************************************************
@ -514,7 +539,7 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
index = next_index; index = next_index;
mbed_minimal_formatted_string_signed(buffer, length, &result, value, stream); mbed_minimal_formatted_string_integer(buffer, length, &result, value, INT_SIGNED, width_size, prepend_zeros, stream);
} }
/* unsigned integer */ /* unsigned integer */
else if ((next == 'u') || (next == 'x') || (next == 'X')) { else if ((next == 'u') || (next == 'x') || (next == 'X')) {
@ -578,9 +603,11 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
/* write unsigned or hexadecimal */ /* write unsigned or hexadecimal */
if (next == 'u') { if (next == 'u') {
mbed_minimal_formatted_string_unsigned(buffer, length, &result, value, stream); mbed_minimal_formatted_string_integer(buffer, length, &result, value, INT_UNSIGNED, width_size, prepend_zeros, stream);
} else if (next == 'X') {
mbed_minimal_formatted_string_integer(buffer, length, &result, value, HEX_UPPER, width_size, prepend_zeros, stream);
} else { } else {
mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value, stream, next == 'X'); mbed_minimal_formatted_string_integer(buffer, length, &result, value, HEX_LOWER, width_size, prepend_zeros, stream);
} }
} }
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT #if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
@ -589,7 +616,7 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
double value = va_arg(arguments, double); double value = va_arg(arguments, double);
index = next_index; index = next_index;
mbed_minimal_formatted_string_double(buffer, length, &result, value, stream); mbed_minimal_formatted_string_double(buffer, length, &result, value, precision, width_size, prepend_zeros, stream);
} }
#endif #endif
/* character */ /* character */
@ -643,4 +670,3 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
return result; return result;
} }

View File

@ -28,6 +28,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <limits.h> #include <limits.h>
#include <inttypes.h> #include <inttypes.h>
#include <cstring>
#ifndef ULLONG_MAX #ifndef ULLONG_MAX
#define ULLONG_MAX UINT64_MAX #define ULLONG_MAX UINT64_MAX
@ -268,6 +269,42 @@ static control_t test_printf_d(const size_t call_count)
TEST_ASSERT_EQUAL_INT(result_baseline, result_file); TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif #endif
result_minimal = mbed_printf("06d: %06d\r\n", -1234);
result_file = mbed_fprintf(stderr, "06d: %06d\r\n", -1234);
result_baseline = sizeof("06d: -01234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("6d: %6d\r\n", -1234);
result_file = mbed_fprintf(stderr, "6d: %6d\r\n", -1234);
result_baseline = sizeof("6d: -1234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("2d: %2d\r\n", -1234);
result_file = mbed_fprintf(stderr, "2d: %2d\r\n", -1234);
result_baseline = sizeof("2d: -1234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("02d: %02d\r\n", -1234);
result_file = mbed_fprintf(stderr, "02d: %02d\r\n", -1234);
result_baseline = sizeof("02d: -1234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("4d: %4d\r\n", 0);
result_file = mbed_fprintf(stderr, "4d: %4d\r\n", 0);
result_baseline = sizeof("4d: 0\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("04d: %04d\r\n", 0);
result_file = mbed_fprintf(stderr, "04d: %04d\r\n", 0);
result_baseline = sizeof("04d: 0000\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
return CaseNext; return CaseNext;
} }
@ -387,6 +424,30 @@ static control_t test_printf_u(const size_t call_count)
TEST_ASSERT_EQUAL_INT(result_baseline, result_file); TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif #endif
result_minimal = mbed_printf("06u: %06u\r\n", 1234);
result_file = mbed_fprintf(stderr, "06u: %06u\r\n", 1234);
result_baseline = sizeof("06u: 001234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("6u: %6u\r\n", 1234);
result_file = mbed_fprintf(stderr, "6u: %6u\r\n", 1234);
result_baseline = sizeof("6u: 1234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("2u: %2u\r\n", 1234);
result_file = mbed_fprintf(stderr, "2u: %2u\r\n", 1234);
result_baseline = sizeof("2u: 1234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("02u: %02u\r\n", 1234);
result_file = mbed_fprintf(stderr, "02u: %02u\r\n", 1234);
result_baseline = sizeof("02u: 1234\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
return CaseNext; return CaseNext;
} }
@ -510,6 +571,43 @@ static control_t test_printf_x(const size_t call_count)
result_baseline = make_test_string("x: ", 11259375, BASE_16, "\r\n"); result_baseline = make_test_string("x: ", 11259375, BASE_16, "\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
// Test prepending zeros and width size
result_minimal = mbed_printf("04X: %04X\r\n", 0x04F6);
result_file = mbed_fprintf(stderr, "04X: %04X\r\n", 0x04F6);
result_baseline = sizeof("04X: 04F6\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("0X: %0X\r\n", 0x04F6);
result_file = mbed_fprintf(stderr, "0X: %0X\r\n", 0x04F6);
result_baseline = sizeof("0X: 4F6\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("6X: %6X\r\n", 0x04F6);
result_file = mbed_fprintf(stderr, "6X: %6X\r\n", 0x04F6);
result_baseline = sizeof("6X: 4F6\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("4X: %4X\r\n", 0xFF04F6);
result_file = mbed_fprintf(stderr, "4X: %4X\r\n", 0xFF04F6);
result_baseline = sizeof("4X: FF04F6\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("4X: %4X\r\n", 0);
result_file = mbed_fprintf(stderr, "4X: %4X\r\n", 0);
result_baseline = sizeof("4X: 0\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("04X: %04X\r\n", 0);
result_file = mbed_fprintf(stderr, "04X: %04X\r\n", 0);
result_baseline = sizeof("04X: 0000\r\n") - 1;
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
return CaseNext; return CaseNext;
} }
@ -640,6 +738,42 @@ static control_t test_snprintf_d(const size_t call_count)
result_minimal = mbed_snprintf(0, 0, "%d + %d = %d\n", a, b, a + b); result_minimal = mbed_snprintf(0, 0, "%d + %d = %d\n", a, b, a + b);
TEST_ASSERT_EQUAL_INT(10, result_minimal); TEST_ASSERT_EQUAL_INT(10, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "06d: %06d\r\n", -1234);
strcpy(expected_string, "06d: -01234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "6d: %6d\r\n", -1234);
strcpy(expected_string, "6d: -1234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "2d: %2d\r\n", -1234);
strcpy(expected_string, "2d: -1234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "02d: %02d\r\n", -1234);
strcpy(expected_string, "02d: -1234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "4d: %4d\r\n", 0);
strcpy(expected_string, "4d: 0\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "04d: %04d\r\n", 0);
strcpy(expected_string, "04d: 0000\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext; return CaseNext;
} }
@ -743,6 +877,30 @@ static control_t test_snprintf_u(const size_t call_count)
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif #endif
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "06u: %06u\r\n", 1234);
strcpy(expected_string, "06u: 001234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "6u: %6u\r\n", 1234);
strcpy(expected_string, "6u: 1234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "2u: %2u\r\n", 1234);
strcpy(expected_string, "2u: 1234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "02u: %02u\r\n", 1234);
strcpy(expected_string, "02u: 1234\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext; return CaseNext;
} }
@ -845,6 +1003,43 @@ static control_t test_snprintf_x(const size_t call_count)
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif #endif
// Test prepending zeros and width size
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "04X: %04X\r\n", 0x04F6);
strcpy(expected_string, "04X: 04F6\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "0X: %0X\r\n", 0x04F6);
strcpy(expected_string, "0X: 4F6\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "6X: %6X\r\n", 0x04F6);
strcpy(expected_string, "6X: 4F6\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "4X: %4X\r\n", 0xFF04F6);
strcpy(expected_string, "4X: FF04F6\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "4X: %4X\r\n", 0);
strcpy(expected_string, "4X: 0\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "04X: %04X\r\n", 0);
strcpy(expected_string, "04X: 0000\r\n");
result_baseline = strlen(expected_string);
TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext; return CaseNext;
} }
@ -914,6 +1109,74 @@ static control_t test_printf_f(const size_t call_count)
result_minimal = mbed_printf("f: %f\r\n", 2.12345649); result_minimal = mbed_printf("f: %f\r\n", 2.12345649);
result_baseline = sprintf(buffer_baseline, "f: 2.123456\r\n"); result_baseline = sprintf(buffer_baseline, "f: 2.123456\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %.3f\r\n", 2.12345649);
result_baseline = sprintf(buffer_baseline, "f: 2.123\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %.8f\r\n", 2.12345649);
result_baseline = sprintf(buffer_baseline, "f: 2.12345649\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %.10f\r\n", 2.12345649);
result_baseline = sprintf(buffer_baseline, "f: 2.1234564900\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %05.3f\r\n", 22.12345649);
result_baseline = sprintf(buffer_baseline, "f: 22.123\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %5.3f\r\n", 22.1);
result_baseline = sprintf(buffer_baseline, "f: 22.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %08.3f\r\n", 22.1);
result_baseline = sprintf(buffer_baseline, "f: 0022.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %8.3f\r\n", 22.1);
result_baseline = sprintf(buffer_baseline, "f: 22.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %05.3f\r\n", -22.12345649);
result_baseline = sprintf(buffer_baseline, "f: -22.123\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %5.3f\r\n", -22.1);
result_baseline = sprintf(buffer_baseline, "f: -22.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %08.3f\r\n", -22.1);
result_baseline = sprintf(buffer_baseline, "f: -022.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %8.3f\r\n", -22.1);
result_baseline = sprintf(buffer_baseline, "f: -22.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %8.3f\r\n", 0.1);
result_baseline = sprintf(buffer_baseline, "f: 0.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %8.3f\r\n", -0.1);
result_baseline = sprintf(buffer_baseline, "f: -0.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %08.3f\r\n", 0.1);
result_baseline = sprintf(buffer_baseline, "f: 0000.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %08.3f\r\n", -0.1);
result_baseline = sprintf(buffer_baseline, "f: -000.100\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("f: %05.3f\r\n", -22.1236);
result_baseline = sprintf(buffer_baseline, "f: -22.124\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_printf("05.0f: %05.0f\r\n", 7.9);
result_baseline = sprintf(buffer_baseline, "05.0f: 00008\r\n");
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext; return CaseNext;
} }
@ -953,7 +1216,86 @@ static control_t test_snprintf_f(const size_t call_count)
result_baseline = sprintf(buffer_baseline, "f: 3.141593\r\n"); result_baseline = sprintf(buffer_baseline, "f: 3.141593\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %.3f\r\n", 2.12345649);
result_baseline = sprintf(buffer_baseline, "f: 2.123\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %.8f\r\n", 2.12345649);
result_baseline = sprintf(buffer_baseline, "f: 2.12345649\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %05.3f\r\n", 22.12345649);
result_baseline = sprintf(buffer_baseline, "f: 22.123\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %5.3f\r\n", 22.1);
result_baseline = sprintf(buffer_baseline, "f: 22.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %08.3f\r\n", 22.1);
result_baseline = sprintf(buffer_baseline, "f: 0022.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %8.3f\r\n", 22.1);
result_baseline = sprintf(buffer_baseline, "f: 22.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %05.3f\r\n", -22.12345649);
result_baseline = sprintf(buffer_baseline, "f: -22.123\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %5.3f\r\n", -22.1);
result_baseline = sprintf(buffer_baseline, "f: -22.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %08.3f\r\n", -22.1);
result_baseline = sprintf(buffer_baseline, "f: -022.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %8.3f\r\n", -22.1);
result_baseline = sprintf(buffer_baseline, "f: -22.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %8.3f\r\n", 0.1);
result_baseline = sprintf(buffer_baseline, "f: 0.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %8.3f\r\n", -0.1);
result_baseline = sprintf(buffer_baseline, "f: -0.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %08.3f\r\n", 0.1);
result_baseline = sprintf(buffer_baseline, "f: 0000.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %08.3f\r\n", -0.1);
result_baseline = sprintf(buffer_baseline, "f: -000.100\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %05.3f\r\n", -22.1236);
result_baseline = sprintf(buffer_baseline, "f: -22.124\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
CLEAN_BUFFER;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "05.0f: %05.0f\r\n", 7.9);
result_baseline = sprintf(buffer_baseline, "05.0f: 00008\r\n");
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext; return CaseNext;
} }
#endif #endif