aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Paland <marco@paland.com>2017-11-13 09:24:41 +0100
committerMarco Paland <marco@paland.com>2017-11-13 09:24:41 +0100
commit4c48045bff631bc0e3bfb0676f3f7dbadb1a3592 (patch)
tree8493bd063626a30df3076c538dfbcb20427d7881
parentaa47054dd8b6fd0b0303a997b8b4149aaa066b47 (diff)
downloadprintf-4c48045bff631bc0e3bfb0676f3f7dbadb1a3592.tar.gz
printf-4c48045bff631bc0e3bfb0676f3f7dbadb1a3592.tar.bz2
printf-4c48045bff631bc0e3bfb0676f3f7dbadb1a3592.zip
Convert _ntoa template in discrete functions
This reduces the compiled size and makes this file 'c' compatible
-rw-r--r--printf.cpp116
1 files 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<typename T>
-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<long long>(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<long>(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<int>(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<unsigned long long>(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<unsigned long>(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<unsigned int>(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<unsigned long long>(reinterpret_cast<unsigned long long>(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<unsigned long>(reinterpret_cast<unsigned long>(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;