aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartijn Jasperse <m.jasperse@gmail.com>2019-02-01 14:38:15 +1100
committerMartijn Jasperse <m.jasperse@gmail.com>2019-02-01 14:38:15 +1100
commit0fea7e5ae428857079f493d56cee50d58d0ed069 (patch)
tree7ccd4599181276ed3c6b01c0432ddd2846a20a2b
parent56d9df0bd3ff3161c86b387c36823a62472980e2 (diff)
downloadprintf-0fea7e5ae428857079f493d56cee50d58d0ed069.tar.gz
printf-0fea7e5ae428857079f493d56cee50d58d0ed069.tar.bz2
printf-0fea7e5ae428857079f493d56cee50d58d0ed069.zip
Fixed whitespace, added %e/%g to README.md
-rw-r--r--README.md5
-rw-r--r--printf.c80
2 files changed, 44 insertions, 41 deletions
diff --git a/README.md b/README.md
index 0b39488..f86b7e4 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Therefore I decided to write an own, final implementation which meets the follow
- Support of decimal/floating number representation (with an own fast itoa/ftoa)
- Reentrant and thread-safe, malloc free, no static vars/buffers
- LINT and compiler L4 warning free, mature, coverity clean, automotive ready
- - Extensive test suite (> 370 test cases) passing
+ - Extensive test suite (> 390 test cases) passing
- Simply the best *printf* around the net
- MIT license
@@ -92,6 +92,8 @@ The following format specifiers are supported:
| x | Unsigned hexadecimal integer (lowercase) |
| X | Unsigned hexadecimal integer (uppercase) |
| f or F | Decimal floating point |
+| e or E | Scientific-notation (exponential) floating point |
+| g or G | Scientific or decimal floating point |
| c | Single character |
| s | String of characters |
| p | Pointer address |
@@ -164,6 +166,7 @@ int length = sprintf(NULL, "Hello, world"); // length is set to 12
| PRINTF_NTOA_BUFFER_SIZE | 32 | ntoa (integer) conversion buffer size. This must be big enough to hold one converted numeric number _including_ leading zeros, normally 32 is a sufficient value. Created on the stack |
| PRINTF_FTOA_BUFFER_SIZE | 32 | ftoa (float) conversion buffer size. This must be big enough to hold one converted float number _including_ leading zeros, normally 32 is a sufficient value. Created on the stack |
| PRINTF_DISABLE_SUPPORT_FLOAT | undefined | Define this to disable floating point (%f) support |
+| PRINTF_DISABLE_SUPPORT_EXPONENTIAL | undefined | Define this to disable exponential floating point (%e) support |
| PRINTF_DISABLE_SUPPORT_LONG_LONG | undefined | Define this to disable long long (%ll) support |
| PRINTF_DISABLE_SUPPORT_PTRDIFF_T | undefined | Define this to disable ptrdiff_t (%t) support |
diff --git a/printf.c b/printf.c
index 62cc52c..99eb7c6 100644
--- a/printf.c
+++ b/printf.c
@@ -106,7 +106,7 @@
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
-#define FLAGS_ADAPT_EXP (1U << 11U)
+#define FLAGS_ADAPT_EXP (1U << 11U)
// output function type
@@ -337,7 +337,7 @@ static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, d
if (value < -DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
if (value > DBL_MAX)
- return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4 : 3, width, flags);
+ return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4 : 3, width, flags);
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
@@ -456,14 +456,14 @@ static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, d
{
// check for special values
if ((value != value)||(value > DBL_MAX)||(value < -DBL_MAX))
- return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
+ return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
// determine the sign
bool negative = value < 0;
if (negative) value = -value;
// determine the decimal exponent
- int expval = (int)floor(log10(value)); // "value" must be +ve
+ int expval = (int)floor(log10(value)); // "value" must be +ve
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
unsigned int minwidth = ((expval < 100)&&(expval > -100)) ? 4 : 5;
@@ -475,23 +475,23 @@ static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, d
// in "%g" mode, "prec" is the number of *significant figures* not decimals
if (flags & FLAGS_ADAPT_EXP) {
- // do we want to fall-back to "%f" mode for small number?
- if ((expval > -5)&&(expval < 6)) {
- if ((int)prec > expval) {
- prec = (unsigned)((int)prec - expval - 1);
+ // do we want to fall-back to "%f" mode for small number?
+ if ((expval > -5)&&(expval < 6)) {
+ if ((int)prec > expval) {
+ prec = (unsigned)((int)prec - expval - 1);
} else {
- prec = 0;
- }
- // TODO: there's also a special case where we're supposed to ELIMINATE digits from the whole part
- flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
-
- // no characters in exponent
- minwidth = 0;
- expval = 0;
- } else {
- // we use one sigfig for the whole part
- if ((prec > 0)&&(flags & FLAGS_PRECISION)) --prec;
- }
+ prec = 0;
+ }
+ // TODO: there's also a special case where we're supposed to ELIMINATE digits from the whole part
+ flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
+
+ // no characters in exponent
+ minwidth = 0;
+ expval = 0;
+ } else {
+ // we use one sigfig for the whole part
+ if ((prec > 0)&&(flags & FLAGS_PRECISION)) --prec;
+ }
}
// will everything fit?
unsigned int fwidth = width;
@@ -499,12 +499,12 @@ static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, d
// we didn't fall-back so subtract the characters required for the exponent
fwidth -= minwidth;
} else {
- // not enough characters, so go back to default sizing
- fwidth = 0;
+ // not enough characters, so go back to default sizing
+ fwidth = 0;
}
if ((flags & FLAGS_LEFT) && minwidth) {
- // if we're padding on the right, DON'T pad the floating part
- fwidth = 0;
+ // if we're padding on the right, DON'T pad the floating part
+ fwidth = 0;
}
// rescale the float value
@@ -516,14 +516,14 @@ static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, d
// output the exponent part
if (minwidth) {
- // output the exponential symbol
- out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
- // output the exponent value
- idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
- // might need to right-pad spaces
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
- }
+ // output the exponential symbol
+ out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
+ // output the exponent value
+ idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
+ // might need to right-pad spaces
+ if (flags & FLAGS_LEFT) {
+ while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
+ }
}
return idx;
}
@@ -716,20 +716,20 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f' :
case 'F' :
- if (*format == 'F') flags |= FLAGS_UPPERCASE;
+ if (*format == 'F') flags |= FLAGS_UPPERCASE;
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
- case 'E':
+ case 'E':
case 'g':
- case 'G':
- if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
- if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
- idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
- format++;
- break;
+ case 'G':
+ if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
+ if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
+ idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
+ format++;
+ break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
case 'c' : {