From 24c460b977c014076821a36b2dae574893cebb85 Mon Sep 17 00:00:00 2001 From: Marco Paland Date: Tue, 15 May 2018 12:14:51 +0200 Subject: feat(printf): added new oprintf() function Write formatted output directly to given output function --- README.md | 3 +++ printf.c | 20 +++++++++++++++++++- printf.h | 12 +++++++++++- test/test_suite.cpp | 10 ++++++++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2c16afd..6583269 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,9 @@ int printf(const char* format, ...); int sprintf(char* buffer, const char* format, ...); int snprintf(char* buffer, size_t count, const char* format, ...); int vsnprintf(char* buffer, size_t count, const char* format, va_list va); + +// write to output function (instead of buffer) +int oprintf(void (*out)(char character), const char* format, ...); ``` diff --git a/printf.c b/printf.c index f1a51e2..0b94d4a 100644 --- a/printf.c +++ b/printf.c @@ -101,6 +101,14 @@ static inline void _out_char(char character, char* buffer, size_t idx, size_t ma } +// internal output function wrapper +static inline void _out_fct(char character, char* buffer, size_t idx, size_t maxlen) +{ + (void)idx; (void)maxlen; + ((void (*)(char character))buffer)(character); // buffer is the output fct pointer +} + + // internal strlen // \return The length of the string (excluding the terminating 0) static inline unsigned int _strlen(const char* str) @@ -674,7 +682,17 @@ int snprintf(char* buffer, size_t count, const char* format, ...) } -inline int vsnprintf(char* buffer, size_t count, const char* format, va_list va) +int vsnprintf(char* buffer, size_t count, const char* format, va_list va) { return _vsnprintf(_out_buffer, buffer, count, format, va); } + + +int oprintf(void (*out)(char character), const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_fct, (char*)out, (size_t)-1, format, va); + va_end(va); + return ret; +} diff --git a/printf.h b/printf.h index 37dbd54..c0ba2ae 100644 --- a/printf.h +++ b/printf.h @@ -60,7 +60,7 @@ int printf(const char* format, ...); /** * Tiny sprintf implementation - * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING SNPRINTF INSTEAD! + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! * \param format A string that specifies the format of the output * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character @@ -80,6 +80,16 @@ int snprintf(char* buffer, size_t count, const char* format, ...); int vsnprintf(char* buffer, size_t count, const char* format, va_list va); +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int oprintf(void (*out)(char character), const char* format, ...); + + #ifdef __cplusplus } #endif diff --git a/test/test_suite.cpp b/test/test_suite.cpp index 9a02b1e..c5614b0 100644 --- a/test/test_suite.cpp +++ b/test/test_suite.cpp @@ -50,8 +50,6 @@ void test::_putchar(char character) TEST_CASE("printf", "[]" ) { - char buffer[100]; - printf_idx = 0U; memset(printf_buffer, 0xCC, 100U); REQUIRE(test::printf("% d", 4232) == 5); @@ -59,6 +57,14 @@ TEST_CASE("printf", "[]" ) { } +TEST_CASE("oprintf", "[]" ) { + printf_idx = 0U; + memset(printf_buffer, 0xCC, 100U); + test::oprintf(&test::_putchar, "This is a test of %X", 0x12EFU); + REQUIRE(!strcmp(printf_buffer, "This is a test of 12EF")); +} + + TEST_CASE("snprintf", "[]" ) { char buffer[100]; -- cgit v1.2.3