From 4c48045bff631bc0e3bfb0676f3f7dbadb1a3592 Mon Sep 17 00:00:00 2001 From: Marco Paland Date: Mon, 13 Nov 2017 09:24:41 +0100 Subject: Convert _ntoa template in discrete functions This reduces the compiled size and makes this file 'c' compatible --- printf.cpp | 116 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 41 deletions(-) diff --git a/printf.cpp b/printf.cpp index 9b46130..3e466b2 100644 --- a/printf.cpp +++ b/printf.cpp @@ -47,6 +47,8 @@ // define this to support floating point (%f) #define PRINTF_FLOAT_SUPPORT +// define this to support long long types (%llu or %p) +#define PRINTF_LONG_LONG_SUPPORT /////////////////////////////////////////////////////////////////////////////// @@ -64,8 +66,8 @@ // internal strlen, returns the length of the string -static inline size_t _strlen(const char* str) -{ +static inline size_t _strlen(const char* str) +{ size_t len = 0U; while (str[len] != '\0') { len++; @@ -92,33 +94,15 @@ static inline unsigned int _atoi(const char** str) } -// internal itoa -template -static size_t _ntoa(T value, char* buffer, unsigned int base, size_t maxlen, unsigned int prec, unsigned int width, unsigned int flags) +// internal itoa format +static size_t _ntoa_format(char* buffer, char* buf, size_t len, bool negative, unsigned int base, size_t maxlen, unsigned int prec, unsigned int width, unsigned int flags) { - char buf[NTOA_BUFFER_SIZE]; - size_t len = 0U; - unsigned int negative = 0U; - if (maxlen == 0U) { return 0U; } if (base > 16U) { return 0U; } - if (value < 0) { - negative = 1U; - value = 0 - value; - } - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || (value != 0)) { - do { - char digit = (char)(value % (T)base); - buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; - value /= (T)base; - } while ((len < NTOA_BUFFER_SIZE) && (value > 0)); - } // pad leading zeros while (!(flags & FLAGS_LEFT) && (len < prec) && (len < NTOA_BUFFER_SIZE)) { @@ -172,7 +156,7 @@ static size_t _ntoa(T value, char* buffer, unsigned int base, size_t maxlen, uns // reverse string for (size_t i = 0U; (i < len) && (i < maxlen); ++i) { - buffer[i] = buf[len - i - 1]; + buffer[i] = buf[len - i - 1U]; } // append pad spaces up to given width @@ -186,24 +170,65 @@ static size_t _ntoa(T value, char* buffer, unsigned int base, size_t maxlen, uns } +// internal itoa for 'long' type +static size_t _ntoa_long(char* buffer, unsigned long value, bool negative, unsigned long base, size_t maxlen, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || (value != 0)) { + do { + char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while ((len < NTOA_BUFFER_SIZE) && (value > 0)); + } + + return _ntoa_format(buffer, buf, len, negative, (unsigned int)base, maxlen, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_LONG_LONG_SUPPORT) +static size_t _ntoa_long_long(char* buffer, unsigned long long value, bool negative, unsigned long long base, size_t maxlen, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || (value != 0)) { + do { + char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while ((len < NTOA_BUFFER_SIZE) && (value > 0)); + } + + return _ntoa_format(buffer, buf, len, negative, (unsigned int)base, maxlen, prec, width, flags); +} +#endif // PRINTF_LONG_LONG_SUPPORT + + #if defined(PRINTF_FLOAT_SUPPORT) static size_t _ftoa(double value, char* buffer, size_t maxlen, unsigned int prec, unsigned int width, unsigned int flags) { - // test for NaN - if (!(value == value) && (maxlen > 2U)) { - buffer[0] = 'n'; buffer[1] = 'a'; buffer[2] = 'n'; - return (size_t)3U; - } + char buf[FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + // if input is larger than thres_max, revert to exponential const double thres_max = (double)0x7FFFFFFF; - char buf[FTOA_BUFFER_SIZE]; - size_t len = 0U; - double diff = 0; - // powers of 10 static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + // test for NaN + if (!(value == value) && (maxlen > 2U)) { + buffer[0] = 'n'; buffer[1] = 'a'; buffer[2] = 'n'; + return (size_t)3U; + } + // limit precision if (!(flags & FLAGS_PRECISION)) { prec = 6U; // by default, precesion is 6 @@ -279,7 +304,7 @@ static size_t _ftoa(double value, char* buffer, size_t maxlen, unsigned int prec break; } } - + // pad leading zeros while (!(flags & FLAGS_LEFT) && (len < prec) && (len < FTOA_BUFFER_SIZE)) { buf[len++] = '0'; @@ -443,25 +468,32 @@ static size_t vsnprintf(char* buffer, size_t buffer_len, const char* format, va_ if ((*format == 'i') || (*format == 'd')) { // signed if (flags & FLAGS_LONG_LONG) { - idx += _ntoa(va_arg(va, long long), &buffer[idx], base, buffer_len - idx, precision, width, flags); +#if defined(PRINTF_LONG_LONG_SUPPORT) + const long long value = va_arg(va, long long); + idx += _ntoa_long_long(&buffer[idx], (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, buffer_len - idx, precision, width, flags); +#endif } else if (flags & FLAGS_LONG) { - idx += _ntoa(va_arg(va, long), &buffer[idx], base, buffer_len - idx, precision, width, flags); + const long value = va_arg(va, long); + idx += _ntoa_long(&buffer[idx], (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, buffer_len - idx, precision, width, flags); } else { - idx += _ntoa(va_arg(va, int), &buffer[idx], base, buffer_len - idx, precision, width, flags); + const int value = va_arg(va, int); + idx += _ntoa_long(&buffer[idx], (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, buffer_len - idx, precision, width, flags); } } else { // unsigned if (flags & FLAGS_LONG_LONG) { - idx += _ntoa(va_arg(va, unsigned long long), &buffer[idx], base, buffer_len - idx, precision, width, flags); +#if defined(PRINTF_LONG_LONG_SUPPORT) + idx += _ntoa_long_long(&buffer[idx], va_arg(va, unsigned long long), false, base, buffer_len - idx, precision, width, flags); +#endif } else if (flags & FLAGS_LONG) { - idx += _ntoa(va_arg(va, unsigned long), &buffer[idx], base, buffer_len - idx, precision, width, flags); + idx += _ntoa_long(&buffer[idx], va_arg(va, unsigned long), false, base, buffer_len - idx, precision, width, flags); } else { - idx += _ntoa(va_arg(va, unsigned int), &buffer[idx], base, buffer_len - idx, precision, width, flags); + idx += _ntoa_long(&buffer[idx], va_arg(va, unsigned int), false, base, buffer_len - idx, precision, width, flags); } } format++; @@ -525,10 +557,12 @@ static size_t vsnprintf(char* buffer, size_t buffer_len, const char* format, va_ flags |= FLAGS_ZEROPAD; size_t size_void = sizeof(void*); if (size_void > sizeof(long)) { - idx +=_ntoa(reinterpret_cast(va_arg(va, void*)), &buffer[idx], 16U, buffer_len - idx, precision, width, flags); +#if defined(PRINTF_LONG_LONG_SUPPORT) + idx += _ntoa_long_long(&buffer[idx], (unsigned long long)va_arg(va, void*), false, 16U, buffer_len - idx, precision, width, flags); +#endif } else { - idx += _ntoa(reinterpret_cast(va_arg(va, void*)), &buffer[idx], 16U, buffer_len - idx, precision, width, flags); + idx += _ntoa_long(&buffer[idx], (unsigned long)va_arg(va, void*), false, 16U, buffer_len - idx, precision, width, flags); } format++; break; -- cgit v1.2.3