mirror of https://github.com/ARMmbed/mbed-os.git
commit
809c7ec16c
|
@ -1,15 +1,15 @@
|
||||||
# Minimal printf and snprintf
|
# Minimal printf and snprintf
|
||||||
|
|
||||||
Library supports both printf and snprintf in 960 bytes of flash.
|
Library supports both printf and snprintf in 1252 bytes of flash.
|
||||||
|
|
||||||
Prints directly to stdio/UART without using malloc. All flags, length, and precision modifiers are ignored. Floating point is disabled by default.
|
Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored. Floating point is disabled by default.
|
||||||
|
|
||||||
Supports:
|
Supports:
|
||||||
* %d: signed long int.
|
* %d: signed integer [h, hh, (none), l, ll, z, j, t].
|
||||||
* %i: signed long int.
|
* %i: signed integer [h, hh, (none), l, ll, z, j, t].
|
||||||
* %u: unsigned long int.
|
* %u: unsigned integer [h, hh, (none), l, ll, z, j, t].
|
||||||
* %x: unsigned char 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 char 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).
|
||||||
* %F: floating point (disabled by default).
|
* %F: floating point (disabled by default).
|
||||||
* %g: floating point (disabled by default).
|
* %g: floating point (disabled by default).
|
||||||
|
|
|
@ -0,0 +1,642 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2017 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "mbed_printf.h"
|
||||||
|
|
||||||
|
#include "utest/utest.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#ifndef ULLONG_MAX
|
||||||
|
#define ULLONG_MAX UINT64_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LLONG_MAX
|
||||||
|
#define LLONG_MAX INT64_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LLONG_MIN
|
||||||
|
#define LLONG_MIN INT64_MIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
|
||||||
|
static control_t test_printf_d(const size_t call_count)
|
||||||
|
{
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MIN);
|
||||||
|
result_baseline = printf("hhd: %hhd\r\n", SCHAR_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MAX);
|
||||||
|
result_baseline = printf("hhd: %hhd\r\n", SCHAR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN);
|
||||||
|
result_baseline = printf("hd: %hd\r\n", SHRT_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX);
|
||||||
|
result_baseline = printf("hd: %hd\r\n", SHRT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("d: %d\r\n", INT_MIN);
|
||||||
|
result_baseline = printf("d: %d\r\n", INT_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("d: %d\r\n", INT_MAX);
|
||||||
|
result_baseline = printf("d: %d\r\n", INT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN);
|
||||||
|
result_baseline = printf("ld: %ld\r\n", LONG_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX);
|
||||||
|
result_baseline = printf("ld: %ld\r\n", LONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN);
|
||||||
|
result_baseline = printf("lld: %lld\r\n", LLONG_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MAX);
|
||||||
|
result_baseline = printf("lld: %lld\r\n", LLONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
printf("%%jd not supported by mbed\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN);
|
||||||
|
result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(17, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX);
|
||||||
|
result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
printf("%%zd not supported by mbed\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN);
|
||||||
|
result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(17, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX);
|
||||||
|
result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
printf("%%td not supported by mbed\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN);
|
||||||
|
result_baseline = printf("td: %td\r\n", PTRDIFF_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_INT(17, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX);
|
||||||
|
result_baseline = printf("td: %td\r\n", PTRDIFF_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static control_t test_printf_u(const size_t call_count)
|
||||||
|
{
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
result_minimal = mbed_printf("hhu: %hhu\r\n", 0);
|
||||||
|
result_baseline = printf("hhu: %hhu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hhu: %hhu\r\n", UCHAR_MAX);
|
||||||
|
result_baseline = printf("hhu: %hhu\r\n", UCHAR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hu: %hu\r\n", 0);
|
||||||
|
result_baseline = printf("hu: %hu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX);
|
||||||
|
result_baseline = printf("hu: %hu\r\n", USHRT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("u: %u\r\n", 0);
|
||||||
|
result_baseline = printf("u: %u\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("u: %u\r\n", UINT_MAX);
|
||||||
|
result_baseline = printf("u: %u\r\n", UINT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("lu: %lu\r\n", 0);
|
||||||
|
result_baseline = printf("lu: %lu\r\n", 0UL);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX);
|
||||||
|
result_baseline = printf("lu: %lu\r\n", ULONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("llu: %llu\r\n", 0);
|
||||||
|
result_baseline = printf("llu: %llu\r\n", 0ULL);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("llu: %llu\r\n", ULLONG_MAX);
|
||||||
|
result_baseline = printf("llu: %llu\r\n", ULLONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("ju: %ju\r\n", 0);
|
||||||
|
result_baseline = printf("ju: %ju\r\n",(uintmax_t) 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX);
|
||||||
|
result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("zu: %zu\r\n", 0);
|
||||||
|
result_baseline = printf("zu: %zu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX);
|
||||||
|
result_baseline = printf("zu: %zu\r\n", SIZE_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("tu: %tu\r\n", 0);
|
||||||
|
result_baseline = printf("tu: %tu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX);
|
||||||
|
result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(26, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static control_t test_printf_x(const size_t call_count)
|
||||||
|
{
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
printf("%%x always prints even characters\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hhX: %hhX\r\n", 0);
|
||||||
|
result_baseline = printf("hhX: %hhX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(9, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX);
|
||||||
|
result_baseline = printf("hhX: %hhX\r\n", UCHAR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hX: %hX\r\n", 0);
|
||||||
|
result_baseline = printf("hX: %hX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX);
|
||||||
|
result_baseline = printf("hX: %hX\r\n", USHRT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("X: %X\r\n", 0);
|
||||||
|
result_baseline = printf("X: %X\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("X: %X\r\n", UINT_MAX);
|
||||||
|
result_baseline = printf("X: %X\r\n", UINT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("lX: %lX\r\n", 0);
|
||||||
|
result_baseline = printf("lX: %lX\r\n", 0UL);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX);
|
||||||
|
result_baseline = printf("lX: %lX\r\n", ULONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("llX: %llX\r\n", 0);
|
||||||
|
result_baseline = printf("llX: %llX\r\n", 0ULL);
|
||||||
|
TEST_ASSERT_EQUAL_INT(9, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX);
|
||||||
|
result_baseline = printf("llX: %llX\r\n", ULLONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("jX: %jX\r\n", 0);
|
||||||
|
result_baseline = printf("jX: %jX\r\n", (uintmax_t) 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX);
|
||||||
|
result_baseline = printf("jX: %jX\r\n", UINTMAX_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("zX: %zX\r\n", 0);
|
||||||
|
result_baseline = printf("zX: %zX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX);
|
||||||
|
result_baseline = printf("zX: %zX\r\n", SIZE_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(14, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("tX: %tX\r\n", 0);
|
||||||
|
result_baseline = printf("tX: %tX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX);
|
||||||
|
result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(22, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* SNPRINTF */
|
||||||
|
/* */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static control_t test_snprintf_d(const size_t call_count)
|
||||||
|
{
|
||||||
|
char buffer_baseline[100];
|
||||||
|
char buffer_minimal[100];
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhd: %hhd\r\n", SCHAR_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhd: %hhd\r\n", SCHAR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hd: %hd\r\n", SHRT_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hd: %hd\r\n", SHRT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "d: %d\r\n", INT_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "d: %d\r\n", INT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ld: %ld\r\n", LONG_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ld: %ld\r\n", LONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lld: %lld\r\n", LLONG_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lld: %lld\r\n", LLONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
printf("%%jd not supported by mbed\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", INT32_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", (intmax_t) INT32_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("jd: -2147483648\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(17, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", INT32_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", (intmax_t) INT32_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("jd: 2147483647\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
printf("%%zd not supported by mbed\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", INT32_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", (ssize_t) INT32_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("zd: -2147483648\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(17, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", INT32_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", (ssize_t) INT32_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("zd: 2147483647\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
printf("%%td not supported by mbed\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MIN);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "td: %td\r\n", PTRDIFF_MIN);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("td: -2147483648\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(17, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "td: %td\r\n", PTRDIFF_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("td: 2147483647\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static control_t test_snprintf_u(const size_t call_count)
|
||||||
|
{
|
||||||
|
char buffer_baseline[100];
|
||||||
|
char buffer_minimal[100];
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhu: %hhu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", UCHAR_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhu: %hhu\r\n", UCHAR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hu: %hu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", USHRT_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hu: %hu\r\n", USHRT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "u: %u\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", UINT_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "u: %u\r\n", UINT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lu: %lu\r\n", 0UL);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", ULONG_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lu: %lu\r\n", ULONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llu: %llu\r\n", 0ULL);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", ULLONG_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llu: %llu\r\n", ULLONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", UINTMAX_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", UINTMAX_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zu: %zu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("zu: 0\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", SIZE_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zu: %zu\r\n", SIZE_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("zu: 4294967295\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(16, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tu: %tu\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("tu: 0\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", UINTPTR_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tu: %tu\r\n", UINTPTR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("tu: 18446744073709551615\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(26, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static control_t test_snprintf_x(const size_t call_count)
|
||||||
|
{
|
||||||
|
char buffer_baseline[100];
|
||||||
|
char buffer_minimal[100];
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
printf("%%x always prints even characters\r\n");
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhX: %hhX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("hhX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(9, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", UCHAR_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhX: %hhX\r\n", UCHAR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hX: %hX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("hX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", USHRT_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hX: %hX\r\n", USHRT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "X: %X\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("X: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", UINT_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "X: %X\r\n", UINT_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lX: %lX\r\n", 0UL);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("lX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", ULONG_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lX: %lX\r\n", ULONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llX: %llX\r\n", 0ULL);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("llX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(9, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", ULLONG_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llX: %llX\r\n", ULLONG_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", (uintmax_t) 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("jX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", UINTMAX_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", UINTMAX_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("jX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zX: %zX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("zX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", SIZE_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zX: %zX\r\n", SIZE_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("zX: FFFFFFFF\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(14, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tX: %tX\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("tX: 00\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", UINTPTR_MAX);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tX: %tX\r\n", UINTPTR_MAX);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("tX: FFFFFFFFFFFFFFFF\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(22, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static control_t test_printf_f(const size_t call_count)
|
||||||
|
{
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
double pi = 3.14159265359;
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("f: %f\r\n", -1 * pi);
|
||||||
|
result_baseline = printf("f: %f\r\n", -1 * pi);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("f: %f\r\n", 0);
|
||||||
|
result_baseline = printf("f: %f\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_printf("f: %f\r\n", pi);
|
||||||
|
result_baseline = printf("f: %f\r\n", pi);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static control_t test_snprintf_f(const size_t call_count)
|
||||||
|
{
|
||||||
|
char buffer_baseline[100];
|
||||||
|
char buffer_minimal[100];
|
||||||
|
int result_baseline;
|
||||||
|
int result_minimal;
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
double pi = 3.14159265359;
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", -1 * pi);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", -1 * pi);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 0);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 0);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("f: 0.0\r\n", buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(8, result_minimal);
|
||||||
|
|
||||||
|
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", pi);
|
||||||
|
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", pi);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
|
||||||
|
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
|
||||||
|
|
||||||
|
return CaseNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
utest::v1::status_t greentea_setup(const size_t number_of_cases)
|
||||||
|
{
|
||||||
|
GREENTEA_SETUP(30*60, "default_auto");
|
||||||
|
return greentea_test_setup_handler(number_of_cases);
|
||||||
|
}
|
||||||
|
|
||||||
|
Case cases[] = {
|
||||||
|
Case("printf %d", test_printf_d),
|
||||||
|
Case("snprintf %d", test_snprintf_d),
|
||||||
|
Case("printf %u", test_printf_u),
|
||||||
|
Case("snprintf %u", test_snprintf_u),
|
||||||
|
Case("printf %x", test_printf_x),
|
||||||
|
Case("snprintf %x", test_snprintf_x),
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
|
||||||
|
Case("printf %f", test_printf_f),
|
||||||
|
Case("snprintf %f", test_snprintf_f),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
Specification specification(greentea_setup, cases, greentea_test_teardown_handler);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return !Harness::run(specification);
|
||||||
|
}
|
|
@ -1,13 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "minimal-printf",
|
"name": "minimal-printf",
|
||||||
"config": {
|
"config": {
|
||||||
"floating-point": {
|
"enable-floating-point": {
|
||||||
"help": "Enable floating point printing",
|
"help": "Enable floating point printing",
|
||||||
"value": false
|
"value": false
|
||||||
},
|
},
|
||||||
"floating-point-max-decimals": {
|
"set-floating-point-max-decimals": {
|
||||||
"help": "Maximum number of decimals to be printed",
|
"help": "Maximum number of decimals to be printed",
|
||||||
"value": 3
|
"value": 6
|
||||||
|
},
|
||||||
|
"enable-64-bit": {
|
||||||
|
"help": "Enable printing 64 bit integers",
|
||||||
|
"value": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* mbed Microcontroller Library
|
/* mbed Microcontroller Library
|
||||||
* Copyright (c) 2016 ARM Limited
|
* Copyright (c) 2017 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,442 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mbed_printf.h"
|
#include "mbed_printf_implementation.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
/* module variable for keeping track of initialization */
|
|
||||||
static bool not_initialized = true;
|
|
||||||
|
|
||||||
/***************************/
|
|
||||||
/* MBED */
|
|
||||||
/***************************/
|
|
||||||
#if TARGET_LIKE_MBED
|
|
||||||
#include "hal/serial_api.h"
|
|
||||||
|
|
||||||
#if DEVICE_SERIAL
|
|
||||||
static serial_t stdio_uart = { 0 };
|
|
||||||
//#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
|
|
||||||
//static char stdio_in_prev = 0;
|
|
||||||
//static char stdio_out_prev = 0;
|
|
||||||
//#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void init_serial()
|
|
||||||
{
|
|
||||||
if (not_initialized)
|
|
||||||
{
|
|
||||||
not_initialized = false;
|
|
||||||
|
|
||||||
#if DEVICE_SERIAL
|
|
||||||
serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
|
|
||||||
#if MBED_CONF_PLATFORM_STDIO_BAUD_RATE
|
|
||||||
serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MBED_INITIALIZE_PRINT(x) { init_serial(); }
|
|
||||||
#define MBED_PRINT_CHARACTER(x) { serial_putc(&stdio_uart, x); }
|
|
||||||
|
|
||||||
/***************************/
|
|
||||||
/* Linux */
|
|
||||||
/***************************/
|
|
||||||
#else
|
|
||||||
#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT 1
|
|
||||||
#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS 10
|
|
||||||
#define MBED_INITIALIZE_PRINT(x) { ; }
|
|
||||||
#define MBED_PRINT_CHARACTER(x) { printf("%c", x); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value);
|
|
||||||
static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value);
|
|
||||||
static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value);
|
|
||||||
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value);
|
|
||||||
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character);
|
|
||||||
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string);
|
|
||||||
|
|
||||||
#ifndef MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT
|
|
||||||
#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS
|
|
||||||
#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value)
|
|
||||||
{
|
|
||||||
/* only continue if buffer can fit at least 1 characters */
|
|
||||||
if ((*result + 1) <= (long int) length)
|
|
||||||
{
|
|
||||||
unsigned long int new_value = 0;
|
|
||||||
|
|
||||||
/* if value is negative print sign and treat as positive number */
|
|
||||||
if (value < 0)
|
|
||||||
{
|
|
||||||
/* write sign */
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
buffer[*result] = '-';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MBED_PRINT_CHARACTER('-');
|
|
||||||
}
|
|
||||||
|
|
||||||
*result += 1;
|
|
||||||
|
|
||||||
/* get absolute value */
|
|
||||||
new_value = (unsigned long int) (-1 * value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new_value = (unsigned long int) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* use unsigned long int function */
|
|
||||||
mbed_minimal_formatted_string_unsigned_long_int(buffer, length, result, new_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value)
|
|
||||||
{
|
|
||||||
/* only continue if buffer can fit at least 1 characters */
|
|
||||||
if ((*result + 1) <= (long int) length)
|
|
||||||
{
|
|
||||||
/* treat 0 as a corner case */
|
|
||||||
if (value == 0)
|
|
||||||
{
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
buffer[*result] = '0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MBED_PRINT_CHARACTER('0');
|
|
||||||
}
|
|
||||||
|
|
||||||
*result += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* allocate 3 digits per byte */
|
|
||||||
char scratch[sizeof(unsigned long int) * 3] = { 0 };
|
|
||||||
|
|
||||||
size_t index = 0;
|
|
||||||
|
|
||||||
/* write numbers in reverse order to scratch pad */
|
|
||||||
for ( ; value > 0; index++)
|
|
||||||
{
|
|
||||||
/* use '0' as base and add digit */
|
|
||||||
scratch[index] = '0' + (value % 10);
|
|
||||||
|
|
||||||
/* shift value one decimal position */
|
|
||||||
value = value / 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write scratch pad to buffer or output */
|
|
||||||
for ( ; (*result < (long int) length) && (index > 0); index--)
|
|
||||||
{
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
buffer[*result] = scratch[index - 1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MBED_PRINT_CHARACTER(scratch[index - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
*result += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value)
|
|
||||||
{
|
|
||||||
/* only continue if buffer can fit at least 2 characters */
|
|
||||||
if ((*result + 2) <= (long int) length)
|
|
||||||
{
|
|
||||||
unsigned int nibble_one = (value & 0xFF) >> 4;
|
|
||||||
unsigned int nibble_two = (value & 0x0F);
|
|
||||||
|
|
||||||
const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
||||||
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
buffer[*result] = int2hex[nibble_one];
|
|
||||||
buffer[*result + 1] = int2hex[nibble_two];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MBED_PRINT_CHARACTER(int2hex[nibble_one]);
|
|
||||||
MBED_PRINT_CHARACTER(int2hex[nibble_two]);
|
|
||||||
}
|
|
||||||
|
|
||||||
*result += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value)
|
|
||||||
{
|
|
||||||
/* only continue if buffer can fit '0x' and twice the size of a void* */
|
|
||||||
if ((*result + 2 + 2 * sizeof(void*)) <= length)
|
|
||||||
{
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
buffer[*result] = '0';
|
|
||||||
buffer[*result + 1] = 'x';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MBED_PRINT_CHARACTER('0');
|
|
||||||
MBED_PRINT_CHARACTER('x');
|
|
||||||
}
|
|
||||||
|
|
||||||
*result += 2;
|
|
||||||
|
|
||||||
for (size_t index = 0; index < sizeof(void*); index++)
|
|
||||||
{
|
|
||||||
unsigned char byte = (unsigned char) (((unsigned long int) value) >> (8 * (sizeof(void*) - index - 1)));
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_unsigned_char(buffer, length, result, byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT
|
|
||||||
static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value)
|
|
||||||
{
|
|
||||||
/* only continue if buffer can fit at least 1 characters */
|
|
||||||
if ((*result + 1) <= (long int) length)
|
|
||||||
{
|
|
||||||
/* get integer part */
|
|
||||||
long int integer = value;
|
|
||||||
|
|
||||||
/* write integer part */
|
|
||||||
mbed_minimal_formatted_string_long_int(buffer, length, result, integer);
|
|
||||||
|
|
||||||
/* write decimal point */
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, result, '.');
|
|
||||||
|
|
||||||
/* get decimal part */
|
|
||||||
double precision = 1.0;
|
|
||||||
|
|
||||||
for (size_t index = 0; index < MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS; index++)
|
|
||||||
{
|
|
||||||
precision *= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
long int decimal = (value - integer) * precision;
|
|
||||||
|
|
||||||
/* take absolute value */
|
|
||||||
if (decimal < 0)
|
|
||||||
{
|
|
||||||
decimal = -1 * decimal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write decimal part */
|
|
||||||
mbed_minimal_formatted_string_long_int(buffer, length, result, decimal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character)
|
|
||||||
{
|
|
||||||
/* only continue if the buffer can fit 1 character */
|
|
||||||
if ((*result + 1) <= (long int) length)
|
|
||||||
{
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
buffer[*result] = (char) character;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MBED_PRINT_CHARACTER((char) character);
|
|
||||||
}
|
|
||||||
|
|
||||||
*result += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string)
|
|
||||||
{
|
|
||||||
/* only continue if the buffer can fit at least 1 character */
|
|
||||||
if ((*result + 1) <= (long int) length)
|
|
||||||
{
|
|
||||||
/* count characters in string */
|
|
||||||
size_t remaining = length - *result;
|
|
||||||
size_t string_length = 0;
|
|
||||||
|
|
||||||
/* only count characters that will fit into buffer */
|
|
||||||
while ((string[string_length] != '\0') && (string_length < remaining))
|
|
||||||
{
|
|
||||||
string_length++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy string to buffer */
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
for (size_t index = 0; index < string_length; index++)
|
|
||||||
{
|
|
||||||
buffer[*result + index] = string[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* print string */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (size_t index = 0; index < string_length; index++)
|
|
||||||
{
|
|
||||||
MBED_PRINT_CHARACTER(string[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add length to counter */
|
|
||||||
*result += string_length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
/* if writing to buffer, reserve space for NULL termination */
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
length--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse string */
|
|
||||||
for (size_t index = 0; format[index] != '\0'; index++)
|
|
||||||
{
|
|
||||||
/* format specifier begin */
|
|
||||||
if (format[index] == '%')
|
|
||||||
{
|
|
||||||
size_t next_index = index + 1;
|
|
||||||
|
|
||||||
/* while there is room in buffer and format string is not empty */
|
|
||||||
while ((next_index < length) && (format[next_index] != '\0') &&
|
|
||||||
/* skip all size modifiers */
|
|
||||||
(((format[next_index] >= '0') && (format[next_index] <= '9')) ||
|
|
||||||
(format[next_index] == 'h') ||
|
|
||||||
(format[next_index] == 'l') ||
|
|
||||||
(format[next_index] == 'j') ||
|
|
||||||
(format[next_index] == 'z') ||
|
|
||||||
(format[next_index] == 't') ||
|
|
||||||
(format[next_index] == 'L') ||
|
|
||||||
(format[next_index] == '.')))
|
|
||||||
{
|
|
||||||
/* skip to next character */
|
|
||||||
next_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read out character - this a supported format character, '\0', or a not suported character */
|
|
||||||
char next = format[next_index];
|
|
||||||
|
|
||||||
/* signed integer */
|
|
||||||
if ((next == 'd') || (next == 'i'))
|
|
||||||
{
|
|
||||||
long int value = va_arg(arguments, long int);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_long_int(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
/* unsigned integer */
|
|
||||||
else if (next == 'u')
|
|
||||||
{
|
|
||||||
unsigned long int value = va_arg(arguments, unsigned long int);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_unsigned_long_int(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
/* treat both hexadecimeal modifiers the same */
|
|
||||||
else if ((next == 'x') || (next == 'X'))
|
|
||||||
{
|
|
||||||
int value = va_arg(arguments, int);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_unsigned_char(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
#if MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT
|
|
||||||
/* treat all floating points the same */
|
|
||||||
else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G'))
|
|
||||||
{
|
|
||||||
double value = va_arg(arguments, double);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_double(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* character */
|
|
||||||
else if (next == 'c')
|
|
||||||
{
|
|
||||||
int value = va_arg(arguments, int);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
/* string */
|
|
||||||
else if (next == 's')
|
|
||||||
{
|
|
||||||
char* value = va_arg(arguments, char*);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_string(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
/* pointer */
|
|
||||||
else if (next == 'p')
|
|
||||||
{
|
|
||||||
void* value = va_arg(arguments, void*);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* write all characters between format beginning and unrecognied modifier */
|
|
||||||
while (index < next_index)
|
|
||||||
{
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if this is not the end of the string, write unrecognized modifier */
|
|
||||||
if (next != '\0')
|
|
||||||
{
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* break out of for loop */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if writing to buffer, NULL terminate string in reserved space*/
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
buffer[result] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbed_printf(const char *format, ...)
|
int mbed_printf(const char *format, ...)
|
||||||
{
|
{
|
||||||
MBED_INITIALIZE_PRINT();
|
|
||||||
|
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments);
|
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments);
|
||||||
|
@ -460,8 +30,6 @@ int mbed_printf(const char *format, ...)
|
||||||
|
|
||||||
int mbed_snprintf(char* buffer, size_t length, const char* format, ...)
|
int mbed_snprintf(char* buffer, size_t length, const char* format, ...)
|
||||||
{
|
{
|
||||||
MBED_INITIALIZE_PRINT();
|
|
||||||
|
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
int result = mbed_minimal_formatted_string(buffer, length, format, arguments);
|
int result = mbed_minimal_formatted_string(buffer, length, format, arguments);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#define MBED_PRINTF_H
|
#define MBED_PRINTF_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -27,14 +28,6 @@ extern "C" {
|
||||||
* Minimal printf
|
* Minimal printf
|
||||||
*
|
*
|
||||||
* Prints directly to stdio/UART without using malloc.
|
* Prints directly to stdio/UART without using malloc.
|
||||||
* Doesn't suppoet any modifiers.
|
|
||||||
*
|
|
||||||
* Supports:
|
|
||||||
* %d: signed long int
|
|
||||||
* %u: unsigned long int
|
|
||||||
* %p: void* (e.g. 0x00123456)
|
|
||||||
* %s: string
|
|
||||||
* %X: unsigned char printed as hexadecimal number (e.g., FF)
|
|
||||||
*/
|
*/
|
||||||
int mbed_printf(const char *format, ...);
|
int mbed_printf(const char *format, ...);
|
||||||
|
|
||||||
|
@ -42,14 +35,6 @@ int mbed_printf(const char *format, ...);
|
||||||
* Minimal snprintf
|
* Minimal snprintf
|
||||||
*
|
*
|
||||||
* Prints directly to buffer without using malloc.
|
* Prints directly to buffer without using malloc.
|
||||||
* Doesn't suppoet any modifiers.
|
|
||||||
*
|
|
||||||
* Supports:
|
|
||||||
* %d: signed long int
|
|
||||||
* %u: unsigned long int
|
|
||||||
* %p: void* (e.g. 0x00123456)
|
|
||||||
* %s: string
|
|
||||||
* %X: unsigned char printed as hexadecimal number (e.g., FF)
|
|
||||||
*/
|
*/
|
||||||
int mbed_snprintf(char* buffer, size_t length, const char* format, ...);
|
int mbed_snprintf(char* buffer, size_t length, const char* format, ...);
|
||||||
|
|
||||||
|
@ -57,14 +42,6 @@ int mbed_snprintf(char* buffer, size_t length, const char* format, ...);
|
||||||
* Minimal printf
|
* Minimal printf
|
||||||
*
|
*
|
||||||
* Prints directly to stdio/UART without using malloc.
|
* Prints directly to stdio/UART without using malloc.
|
||||||
* Doesn't suppoet any modifiers.
|
|
||||||
*
|
|
||||||
* Supports:
|
|
||||||
* %d: signed long int
|
|
||||||
* %u: unsigned long int
|
|
||||||
* %p: void* (e.g. 0x00123456)
|
|
||||||
* %s: string
|
|
||||||
* %X: unsigned char printed as hexadecimal number (e.g., FF)
|
|
||||||
*/
|
*/
|
||||||
int mbed_vprintf(const char* format, va_list arguments);
|
int mbed_vprintf(const char* format, va_list arguments);
|
||||||
|
|
||||||
|
@ -72,14 +49,6 @@ int mbed_vprintf(const char* format, va_list arguments);
|
||||||
* Minimal snprintf
|
* Minimal snprintf
|
||||||
*
|
*
|
||||||
* Prints directly to buffer without using malloc.
|
* Prints directly to buffer without using malloc.
|
||||||
* Doesn't suppoet any modifiers.
|
|
||||||
*
|
|
||||||
* Supports:
|
|
||||||
* %d: signed long int
|
|
||||||
* %u: unsigned long int
|
|
||||||
* %p: void* (e.g. 0x00123456)
|
|
||||||
* %s: string
|
|
||||||
* %X: unsigned char printed as hexadecimal number (e.g., FF)
|
|
||||||
*/
|
*/
|
||||||
int mbed_vsnprintf(char* buffer, size_t length, const char* format, va_list arguments);
|
int mbed_vsnprintf(char* buffer, size_t length, const char* format, va_list arguments);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,756 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2017 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mbed_printf_implementation.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************/
|
||||||
|
/* MBED */
|
||||||
|
/***************************/
|
||||||
|
#if TARGET_LIKE_MBED
|
||||||
|
/*
|
||||||
|
Serial initialization and new line replacement is a direct copy from mbed_retarget.cpp
|
||||||
|
If the static modifier were to be removed, this part of the code would not be necessary.
|
||||||
|
*/
|
||||||
|
#include "hal/serial_api.h"
|
||||||
|
|
||||||
|
#if DEVICE_SERIAL
|
||||||
|
static serial_t stdio_uart = { 0 };
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
|
||||||
|
static char mbed_stdio_out_prev = 0;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* module variable for keeping track of initialization */
|
||||||
|
static bool not_initialized = true;
|
||||||
|
|
||||||
|
static void init_serial()
|
||||||
|
{
|
||||||
|
if (not_initialized)
|
||||||
|
{
|
||||||
|
not_initialized = false;
|
||||||
|
|
||||||
|
#if DEVICE_SERIAL
|
||||||
|
serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_BAUD_RATE
|
||||||
|
serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MBED_INITIALIZE_PRINT(x) { init_serial(); }
|
||||||
|
#define MBED_PRINT_CHARACTER(x) { serial_putc(&stdio_uart, x); }
|
||||||
|
|
||||||
|
/***************************/
|
||||||
|
/* Linux */
|
||||||
|
/***************************/
|
||||||
|
#else
|
||||||
|
/* Linux implementation is for debug only */
|
||||||
|
#define MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 1
|
||||||
|
#define MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 6
|
||||||
|
#define MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT 1
|
||||||
|
#define MBED_INITIALIZE_PRINT(x) { ; }
|
||||||
|
#define MBED_PRINT_CHARACTER(x) { printf("%c", x); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
|
||||||
|
#define MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS
|
||||||
|
#define MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
||||||
|
#define MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check architecture and choose storage data type.
|
||||||
|
* On 32 bit machines, the default storage type is 32 bit wide
|
||||||
|
* unless 64 bit integers are enabled in the configuration.
|
||||||
|
*/
|
||||||
|
#if INTPTR_MAX == INT32_MAX
|
||||||
|
#define MBED_SIGNED_NATIVE_TYPE int32_t
|
||||||
|
#define MBED_UNSIGNED_NATIVE_TYPE uint32_t
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
||||||
|
#define MBED_SIGNED_STORAGE int64_t
|
||||||
|
#define MBED_UNSIGNED_STORAGE uint64_t
|
||||||
|
#else
|
||||||
|
#define MBED_SIGNED_STORAGE int32_t
|
||||||
|
#define MBED_UNSIGNED_STORAGE uint32_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif INTPTR_MAX == INT64_MAX
|
||||||
|
#define MBED_SIGNED_NATIVE_TYPE int64_t
|
||||||
|
#define MBED_UNSIGNED_NATIVE_TYPE uint64_t
|
||||||
|
#define MBED_SIGNED_STORAGE int64_t
|
||||||
|
#define MBED_UNSIGNED_STORAGE uint64_t
|
||||||
|
#else
|
||||||
|
#error unsupported architecture
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum for storing width modifier.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
LENGTH_NONE,
|
||||||
|
LENGTH_HH,
|
||||||
|
LENGTH_H,
|
||||||
|
LENGTH_L,
|
||||||
|
LENGTH_LL,
|
||||||
|
LENGTH_J,
|
||||||
|
LENGTH_Z,
|
||||||
|
LENGTH_T,
|
||||||
|
LENGTH_CAPITAL_L
|
||||||
|
} length_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prototypes
|
||||||
|
*/
|
||||||
|
static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value);
|
||||||
|
static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value);
|
||||||
|
static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value);
|
||||||
|
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value);
|
||||||
|
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character);
|
||||||
|
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print signed 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_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value)
|
||||||
|
{
|
||||||
|
/* only continue if buffer can fit at least 1 characters */
|
||||||
|
if ((size_t)(*result + 1) <= length)
|
||||||
|
{
|
||||||
|
MBED_UNSIGNED_STORAGE new_value = 0;
|
||||||
|
|
||||||
|
/* if value is negative print sign and treat as positive number */
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
/* write sign */
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
buffer[*result] = '-';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MBED_PRINT_CHARACTER('-');
|
||||||
|
}
|
||||||
|
|
||||||
|
*result += 1;
|
||||||
|
|
||||||
|
/* get absolute value using two's complement */
|
||||||
|
new_value = ~((MBED_UNSIGNED_STORAGE) value) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use unsigned long int function */
|
||||||
|
mbed_minimal_formatted_string_unsigned(buffer, length, result, new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
|
{
|
||||||
|
/* only continue if buffer can fit at least 1 characters */
|
||||||
|
if ((size_t)(*result + 1) <= length)
|
||||||
|
{
|
||||||
|
/* treat 0 as a corner case */
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
buffer[*result] = '0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MBED_PRINT_CHARACTER('0');
|
||||||
|
}
|
||||||
|
|
||||||
|
*result += 1;
|
||||||
|
}
|
||||||
|
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 */
|
||||||
|
for ( ; value > 0; index++)
|
||||||
|
{
|
||||||
|
/* use '0' as base and add digit */
|
||||||
|
scratch[index] = '0' + (value % 10);
|
||||||
|
|
||||||
|
/* shift value one decimal position */
|
||||||
|
value = value / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write scratch pad to buffer or output */
|
||||||
|
for ( ; ((size_t)*result < length) && (index > 0); index--)
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
buffer[*result] = scratch[index - 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MBED_PRINT_CHARACTER(scratch[index - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
*result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print hexadecimal.
|
||||||
|
*
|
||||||
|
* @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_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value)
|
||||||
|
{
|
||||||
|
bool print_leading_zero = false;
|
||||||
|
|
||||||
|
/* only continue each loop if buffer can fit at least 2 characters */
|
||||||
|
for (ssize_t index = 7; (((size_t)(*result + 2) <= length)) && (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))
|
||||||
|
{
|
||||||
|
/* print zeroes after the first non-zero byte */
|
||||||
|
print_leading_zero = true;
|
||||||
|
|
||||||
|
unsigned int nibble_one = (output >> 4);
|
||||||
|
unsigned int nibble_two = (output & 0x0F);
|
||||||
|
|
||||||
|
const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||||
|
|
||||||
|
/* write to buffer or stdout */
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
buffer[*result] = int2hex[nibble_one];
|
||||||
|
buffer[*result + 1] = int2hex[nibble_two];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MBED_PRINT_CHARACTER(int2hex[nibble_one]);
|
||||||
|
MBED_PRINT_CHARACTER(int2hex[nibble_two]);
|
||||||
|
}
|
||||||
|
|
||||||
|
*result += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print pointer.
|
||||||
|
*
|
||||||
|
* @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 pointer to be printed.
|
||||||
|
*/
|
||||||
|
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value)
|
||||||
|
{
|
||||||
|
/* only continue if buffer can fit '0x' and twice the size of a void* */
|
||||||
|
if ((*result + 2 + 2 * sizeof(void*)) <= length)
|
||||||
|
{
|
||||||
|
/* write leading 0x */
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
buffer[*result] = '0';
|
||||||
|
buffer[*result + 1] = 'x';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MBED_PRINT_CHARACTER('0');
|
||||||
|
MBED_PRINT_CHARACTER('x');
|
||||||
|
}
|
||||||
|
|
||||||
|
*result += 2;
|
||||||
|
|
||||||
|
/* write rest as a regular hexadecimal number */
|
||||||
|
mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
|
||||||
|
/**
|
||||||
|
* @brief Write double.
|
||||||
|
*
|
||||||
|
* @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_double(char* buffer, size_t length, int* result, double value)
|
||||||
|
{
|
||||||
|
/* only continue if buffer can fit at least 1 characters */
|
||||||
|
if ((size_t)(*result + 1) <= length)
|
||||||
|
{
|
||||||
|
/* get integer part */
|
||||||
|
MBED_SIGNED_STORAGE integer = value;
|
||||||
|
|
||||||
|
/* write integer part */
|
||||||
|
mbed_minimal_formatted_string_signed(buffer, length, result, integer);
|
||||||
|
|
||||||
|
/* write decimal point */
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, result, '.');
|
||||||
|
|
||||||
|
/* get decimal part */
|
||||||
|
double precision = 1.0;
|
||||||
|
|
||||||
|
for (size_t index = 0; index < MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS; index++)
|
||||||
|
{
|
||||||
|
precision *= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (value - integer) * precision;
|
||||||
|
|
||||||
|
/* convert to unsigned integer */
|
||||||
|
MBED_UNSIGNED_STORAGE decimal = 0;
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
MBED_SIGNED_STORAGE temp = value;
|
||||||
|
decimal = ~((MBED_UNSIGNED_STORAGE) temp) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decimal = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* round up or down */
|
||||||
|
value -= decimal;
|
||||||
|
|
||||||
|
if (!((value > -0.5) && (value < 0.5)))
|
||||||
|
{
|
||||||
|
decimal++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write decimal part */
|
||||||
|
mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print character.
|
||||||
|
*
|
||||||
|
* @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 character to be printed.
|
||||||
|
*/
|
||||||
|
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character)
|
||||||
|
{
|
||||||
|
/* only continue if the buffer can fit 1 character */
|
||||||
|
if ((size_t)(*result + 1) <= length)
|
||||||
|
{
|
||||||
|
/* write character */
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
buffer[*result] = character;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* convert \n to \r\n if enabled in platform configuration */
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
|
||||||
|
if (character == '\n' && mbed_stdio_out_prev != '\r')
|
||||||
|
{
|
||||||
|
MBED_PRINT_CHARACTER('\r');
|
||||||
|
*result += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cache character */
|
||||||
|
mbed_stdio_out_prev = character;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* write character to stdout */
|
||||||
|
MBED_PRINT_CHARACTER(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
*result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print string.
|
||||||
|
*
|
||||||
|
* @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 string to be printed.
|
||||||
|
*/
|
||||||
|
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string)
|
||||||
|
{
|
||||||
|
/* only continue if the buffer can fit at least 1 character */
|
||||||
|
if ((size_t)(*result + 1) <= length)
|
||||||
|
{
|
||||||
|
/* count characters in string */
|
||||||
|
size_t remaining = length - *result;
|
||||||
|
size_t string_length = 0;
|
||||||
|
|
||||||
|
/* only count characters that will fit into buffer */
|
||||||
|
while ((string[string_length] != '\0') && (string_length < remaining))
|
||||||
|
{
|
||||||
|
string_length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy string to buffer */
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
for (size_t index = 0; index < string_length; index++)
|
||||||
|
{
|
||||||
|
buffer[*result + index] = string[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* print string */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t index = 0; index < string_length; index++)
|
||||||
|
{
|
||||||
|
MBED_PRINT_CHARACTER(string[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add length to counter */
|
||||||
|
*result += string_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse formatted string and invoke write handlers based on type.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to write to, write to stdout if NULL.
|
||||||
|
* @param[in] length The length of the buffer.
|
||||||
|
* @param[in] format The formatted string.
|
||||||
|
* @param[in] arguments The va_list arguments.
|
||||||
|
*
|
||||||
|
* @return Number of characters written.
|
||||||
|
*/
|
||||||
|
int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments)
|
||||||
|
{
|
||||||
|
/* initialize output if needed */
|
||||||
|
MBED_INITIALIZE_PRINT();
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
/* if writing to buffer, reserve space for NULL termination */
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse string */
|
||||||
|
for (size_t index = 0; format[index] != '\0'; index++)
|
||||||
|
{
|
||||||
|
/* format specifier begin */
|
||||||
|
if (format[index] == '%')
|
||||||
|
{
|
||||||
|
size_t next_index = index + 1;
|
||||||
|
|
||||||
|
/* while there is room in buffer and format string is not empty */
|
||||||
|
while ((next_index < length) && (format[next_index] != '\0') &&
|
||||||
|
/* skip all flags and precision modifiers */
|
||||||
|
(((format[next_index] >= '0') && (format[next_index] <= '9')) ||
|
||||||
|
(format[next_index] == '-') ||
|
||||||
|
(format[next_index] == '+') ||
|
||||||
|
(format[next_index] == '#') ||
|
||||||
|
(format[next_index] == '.')))
|
||||||
|
{
|
||||||
|
/* skip to next character */
|
||||||
|
next_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for length modifier, default to NONE */
|
||||||
|
length_t length_modifier = LENGTH_NONE;
|
||||||
|
|
||||||
|
/* look for two character length modifier */
|
||||||
|
if (format[next_index + 1] != '\0')
|
||||||
|
{
|
||||||
|
if ((format[next_index] == 'h') && (format[next_index + 1] == 'h'))
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_HH;
|
||||||
|
}
|
||||||
|
else if ((format[next_index] == 'l') && (format[next_index + 1] == 'l'))
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment next_index if length modifier was found */
|
||||||
|
if (length_modifier != LENGTH_NONE)
|
||||||
|
{
|
||||||
|
next_index += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for one character length modifier if two character search failed */
|
||||||
|
if ((length_modifier == LENGTH_NONE) && (format[next_index] != '\0'))
|
||||||
|
{
|
||||||
|
if (format[next_index] == 'h')
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_H;
|
||||||
|
}
|
||||||
|
else if (format[next_index] == 'l')
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_L;
|
||||||
|
}
|
||||||
|
else if (format[next_index] == 'j')
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_J;
|
||||||
|
}
|
||||||
|
else if (format[next_index] == 'z')
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_Z;
|
||||||
|
}
|
||||||
|
else if (format[next_index] == 't')
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_T;
|
||||||
|
}
|
||||||
|
else if (format[next_index] == 'L')
|
||||||
|
{
|
||||||
|
length_modifier = LENGTH_CAPITAL_L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment next_index if length modifier was found */
|
||||||
|
if (length_modifier != LENGTH_NONE)
|
||||||
|
{
|
||||||
|
next_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read out character - this is a supported format character, '\0', or a not suported character */
|
||||||
|
char next = format[next_index];
|
||||||
|
|
||||||
|
/* signed integer */
|
||||||
|
if ((next == 'd') || (next == 'i'))
|
||||||
|
{
|
||||||
|
MBED_SIGNED_STORAGE value = 0;
|
||||||
|
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
||||||
|
/* if 64 bit is enabled and the integer types are larger than the native type */
|
||||||
|
if (((length_modifier == LENGTH_LL) && (sizeof(long long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_L) && (sizeof(long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_NONE) && (sizeof(int) > sizeof(MBED_SIGNED_NATIVE_TYPE))))
|
||||||
|
{
|
||||||
|
/* use 64 bit storage type for readout */
|
||||||
|
value = va_arg(arguments, MBED_SIGNED_STORAGE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* use native storage type (which can be 32 or 64 bit) */
|
||||||
|
value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constrict value based on lenght modifier */
|
||||||
|
switch (length_modifier)
|
||||||
|
{
|
||||||
|
case LENGTH_NONE:
|
||||||
|
value = (int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_HH:
|
||||||
|
value = (signed char) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_H:
|
||||||
|
value = (short int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_L:
|
||||||
|
value = (long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_LL:
|
||||||
|
value = (long long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_J:
|
||||||
|
value = (intmax_t) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_Z:
|
||||||
|
value = (ssize_t) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_T:
|
||||||
|
value = (ptrdiff_t) value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_signed(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
/* unsigned integer */
|
||||||
|
else if ((next == 'u') || (next == 'x') || (next == 'X'))
|
||||||
|
{
|
||||||
|
MBED_UNSIGNED_STORAGE value = 0;
|
||||||
|
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
||||||
|
/* if 64 bit is enabled and the integer types are larger than the native type */
|
||||||
|
if (((length_modifier == LENGTH_LL) && (sizeof(unsigned long long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_L) && (sizeof(unsigned long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_NONE) && (sizeof(unsigned int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))))
|
||||||
|
{
|
||||||
|
/* use 64 bit storage type for readout */
|
||||||
|
value = va_arg(arguments, MBED_UNSIGNED_STORAGE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* use native storage type (which can be 32 or 64 bit) */
|
||||||
|
value = va_arg(arguments, MBED_UNSIGNED_NATIVE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constrict value based on lenght modifier */
|
||||||
|
switch (length_modifier)
|
||||||
|
{
|
||||||
|
case LENGTH_NONE:
|
||||||
|
value = (unsigned int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_HH:
|
||||||
|
value = (unsigned char) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_H:
|
||||||
|
value = (unsigned short int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_L:
|
||||||
|
value = (unsigned long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_LL:
|
||||||
|
value = (unsigned long long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_J:
|
||||||
|
value = (uintmax_t) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_Z:
|
||||||
|
value = (size_t) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_T:
|
||||||
|
value = (ptrdiff_t) value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
/* write unsigned or hexadecimal */
|
||||||
|
if (next == 'u')
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_unsigned(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
|
||||||
|
/* treat all floating points the same */
|
||||||
|
else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G'))
|
||||||
|
{
|
||||||
|
double value = va_arg(arguments, double);
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_double(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* character */
|
||||||
|
else if (next == 'c')
|
||||||
|
{
|
||||||
|
char value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
/* string */
|
||||||
|
else if (next == 's')
|
||||||
|
{
|
||||||
|
char* value = va_arg(arguments, char*);
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_string(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
/* pointer */
|
||||||
|
else if (next == 'p')
|
||||||
|
{
|
||||||
|
void* value = va_arg(arguments, void*);
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* write all characters between format beginning and unrecognied modifier */
|
||||||
|
while (index < next_index)
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if this is not the end of the string, write unrecognized modifier */
|
||||||
|
if (next != '\0')
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* break out of for loop */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* not a format specifier */
|
||||||
|
{
|
||||||
|
/* write normal character */
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if writing to buffer, NULL terminate string in reserved space*/
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
buffer[result] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2017 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments);
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2017 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mbed_printf_implementation.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#if defined(TOOLCHAIN_GCC)
|
||||||
|
#define SUB_PRINTF __wrap_printf
|
||||||
|
#define SUB_SNPRINTF __wrap_snprintf
|
||||||
|
#define SUB_SPRINTF __wrap_sprintf
|
||||||
|
#define SUB_VSNPRINTF __wrap_vsnprintf
|
||||||
|
#elif defined(TOOLCHAIN_ARM)
|
||||||
|
#define SUPER_PRINTF $Super$$printf
|
||||||
|
#define SUB_PRINTF $Sub$$printf
|
||||||
|
#define SUPER_SNPRINTF $Super$$snprintf
|
||||||
|
#define SUB_SNPRINTF $Sub$$snprintf
|
||||||
|
#define SUPER_SPRINTF $Super$$sprintf
|
||||||
|
#define SUB_SPRINTF $Sub$$sprintf
|
||||||
|
#define SUPER_VSNPRINTF $Super$$vsnprintf
|
||||||
|
#define SUB_VSNPRINTF $Sub$$vsnprintf
|
||||||
|
#elif defined(__ICCARM__)
|
||||||
|
#define SUPER_PRINTF $Super$$__iar_printf
|
||||||
|
#define SUB_PRINTF $Sub$$__iar_printf
|
||||||
|
#define SUPER_SNPRINTF $Super$$__iar_snprintf
|
||||||
|
#define SUB_SNPRINTF $Sub$$__iar_snprintf
|
||||||
|
#define SUPER_SPRINTF $Super$$__iar_sprintf
|
||||||
|
#define SUB_SPRINTF $Sub$$__iar_sprintf
|
||||||
|
#define SUPER_VSNPRINTF $Super$$__iar_vsnprintf
|
||||||
|
#define SUB_VSNPRINTF $Sub$$__iar_vsnprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int SUB_PRINTF(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list arguments;
|
||||||
|
va_start(arguments, format);
|
||||||
|
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments);
|
||||||
|
va_end(arguments);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SUB_SNPRINTF(char* buffer, size_t length, const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list arguments;
|
||||||
|
va_start(arguments, format);
|
||||||
|
int result = mbed_minimal_formatted_string(buffer, length, format, arguments);
|
||||||
|
va_end(arguments);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SUB_SPRINTF(char* buffer, const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list arguments;
|
||||||
|
va_start(arguments, format);
|
||||||
|
int result = mbed_minimal_formatted_string(buffer, LONG_MAX, format, arguments);
|
||||||
|
va_end(arguments);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SUB_VSNPRINTF(char* buffer, size_t length, const char* format, va_list arguments)
|
||||||
|
{
|
||||||
|
return mbed_minimal_formatted_string(buffer, length, format, arguments);
|
||||||
|
}
|
Loading…
Reference in New Issue