42 #ifdef PRINTF_INCLUDE_CONFIG_H
43 #include "printf_config.h"
50 #ifndef PRINTF_NTOA_BUFFER_SIZE
51 #define PRINTF_NTOA_BUFFER_SIZE 32U
57 #ifndef PRINTF_FTOA_BUFFER_SIZE
58 #define PRINTF_FTOA_BUFFER_SIZE 32U
63 #ifndef PRINTF_DISABLE_SUPPORT_FLOAT
64 #define PRINTF_SUPPORT_FLOAT
69 #ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
70 #define PRINTF_SUPPORT_EXPONENTIAL
75 #ifndef PRINTF_DEFAULT_FLOAT_PRECISION
76 #define PRINTF_DEFAULT_FLOAT_PRECISION 6U
81 #ifndef PRINTF_MAX_FLOAT
82 #define PRINTF_MAX_FLOAT 1e9
87 #ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
88 #define PRINTF_SUPPORT_LONG_LONG
94 #ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
95 #define PRINTF_SUPPORT_PTRDIFF_T
101 #define FLAGS_ZEROPAD (1U << 0U)
102 #define FLAGS_LEFT (1U << 1U)
103 #define FLAGS_PLUS (1U << 2U)
104 #define FLAGS_SPACE (1U << 3U)
105 #define FLAGS_HASH (1U << 4U)
106 #define FLAGS_UPPERCASE (1U << 5U)
107 #define FLAGS_CHAR (1U << 6U)
108 #define FLAGS_SHORT (1U << 7U)
109 #define FLAGS_LONG (1U << 8U)
110 #define FLAGS_LONG_LONG (1U << 9U)
111 #define FLAGS_PRECISION (1U << 10U)
112 #define FLAGS_ADAPT_EXP (1U << 11U)
116 #if defined(PRINTF_SUPPORT_FLOAT)
121 typedef void (*
out_fct_type)(
char character,
void* buffer,
size_t idx,
size_t maxlen);
126 void (*fct)(
char character,
void* arg);
132 static inline void _out_buffer(
char character,
void* buffer,
size_t idx,
size_t maxlen)
135 ((
char*)buffer)[idx] = character;
141 static inline void _out_null(
char character,
void* buffer,
size_t idx,
size_t maxlen)
143 (void)character; (void)buffer; (void)idx; (void)maxlen;
148 static inline void _out_char(
char character,
void* buffer,
size_t idx,
size_t maxlen)
150 (void)buffer; (void)idx; (void)maxlen;
158 static inline void _out_fct(
char character,
void* buffer,
size_t idx,
size_t maxlen)
160 (void)idx; (void)maxlen;
170 static inline unsigned int _strnlen_s(
const char* str,
size_t maxsize)
173 for (s = str; *s && maxsize--; ++s);
174 return (
unsigned int)(s - str);
182 return (ch >=
'0') && (ch <=
'9');
187 static unsigned int _atoi(
const char** str)
191 i = i * 10U + (
unsigned int)(*((*str)++) -
'0');
198 static size_t _out_rev(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
const char* buf,
size_t len,
unsigned int width,
unsigned int flags)
200 const size_t start_idx = idx;
204 for (
size_t i = len; i < width; i++) {
205 out(
' ', buffer, idx++, maxlen);
211 out(buf[--len], buffer, idx++, maxlen);
216 while (idx - start_idx < width) {
217 out(
' ', buffer, idx++, maxlen);
226 static size_t _ntoa_format(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
char* buf,
size_t len,
bool negative,
unsigned int base,
unsigned int prec,
unsigned int width,
unsigned int flags)
243 if (!(flags &
FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
245 if (len && (base == 16U)) {
275 return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
280 static size_t _ntoa_long(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
unsigned long value,
bool negative,
unsigned long base,
unsigned int prec,
unsigned int width,
unsigned int flags)
293 const char digit = (char)(value % base);
294 buf[len++] = digit < 10 ?
'0' + digit : (flags &
FLAGS_UPPERCASE ?
'A' :
'a') + digit - 10;
299 return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (
unsigned int)base, prec, width, flags);
304 #if defined(PRINTF_SUPPORT_LONG_LONG)
305 static size_t _ntoa_long_long(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
unsigned long long value,
bool negative,
unsigned long long base,
unsigned int prec,
unsigned int width,
unsigned int flags)
318 const char digit = (char)(value % base);
319 buf[len++] = digit < 10 ?
'0' + digit : (flags &
FLAGS_UPPERCASE ?
'A' :
'a') + digit - 10;
324 return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (
unsigned int)base, prec, width, flags);
326 #endif // PRINTF_SUPPORT_LONG_LONG
329 #if defined(PRINTF_SUPPORT_FLOAT)
331 #if defined(PRINTF_SUPPORT_EXPONENTIAL)
333 static size_t _etoa(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
double value,
unsigned int prec,
unsigned int width,
unsigned int flags);
338 static size_t _ftoa(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
double value,
unsigned int prec,
unsigned int width,
unsigned int flags)
345 static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
349 return _out_rev(out, buffer, idx, maxlen,
"nan", 3, width, flags);
350 if (value < -DBL_MAX)
351 return _out_rev(out, buffer, idx, maxlen,
"fni-", 4, width, flags);
358 #if defined(PRINTF_SUPPORT_EXPONENTIAL)
359 return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
366 bool negative =
false;
382 int whole = (int)value;
383 double tmp = (value - whole) * pow10[prec];
384 unsigned long frac = (
unsigned long)tmp;
390 if (frac >= pow10[prec]) {
395 else if (diff < 0.5) {
397 else if ((frac == 0U) || (frac & 1U)) {
403 diff = value - (double)whole;
404 if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
411 unsigned int count = prec;
415 buf[len++] = (char)(48U + (frac % 10U));
416 if (!(frac /= 10U)) {
432 buf[len++] = (char)(48 + (whole % 10));
433 if (!(whole /= 10)) {
460 return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
464 #if defined(PRINTF_SUPPORT_EXPONENTIAL)
466 static size_t _etoa(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
double value,
unsigned int prec,
unsigned int width,
unsigned int flags)
469 if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
470 return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
474 const bool negative = value < 0;
492 int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023;
493 conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U);
495 int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
497 exp2 = (int)(expval * 3.321928094887362 + 0.5);
498 const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
499 const double z2 = z * z;
500 conv.U = (uint64_t)(exp2 + 1023) << 52U;
502 conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
504 if (value < conv.F) {
510 unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
515 if ((value >= 1e-4) && (value < 1e6)) {
516 if ((
int)prec > expval) {
517 prec = (unsigned)((
int)prec - expval - 1);
536 unsigned int fwidth = width;
537 if (width > minwidth) {
555 const size_t start_idx = idx;
556 idx =
_ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~
FLAGS_ADAPT_EXP);
566 while (idx - start_idx < width) out(
' ', buffer, idx++, maxlen);
571 #endif // PRINTF_SUPPORT_EXPONENTIAL
572 #endif // PRINTF_SUPPORT_FLOAT
578 unsigned int flags, width, precision, n;
589 if (*format !=
'%') {
591 out(*format, buffer, idx++, maxlen);
605 case '-': flags |=
FLAGS_LEFT; format++; n = 1U;
break;
606 case '+': flags |=
FLAGS_PLUS; format++; n = 1U;
break;
607 case ' ': flags |=
FLAGS_SPACE; format++; n = 1U;
break;
608 case '#': flags |=
FLAGS_HASH; format++; n = 1U;
break;
609 default : n = 0U;
break;
616 width =
_atoi(&format);
618 else if (*format ==
'*') {
619 const int w = va_arg(va,
int);
622 width = (
unsigned int)-w;
625 width = (
unsigned int)w;
632 if (*format ==
'.') {
636 precision =
_atoi(&format);
638 else if (*format ==
'*') {
639 const int prec = (int)va_arg(va,
int);
640 precision = prec > 0 ? (
unsigned int)prec : 0U;
650 if (*format ==
'l') {
658 if (*format ==
'h') {
663 #if defined(PRINTF_SUPPORT_PTRDIFF_T)
692 if (*format ==
'x' || *format ==
'X') {
695 else if (*format ==
'o') {
698 else if (*format ==
'b') {
706 if (*format ==
'X') {
711 if ((*format !=
'i') && (*format !=
'd')) {
721 if ((*format ==
'i') || (*format ==
'd')) {
724 #if defined(PRINTF_SUPPORT_LONG_LONG)
725 const long long value = va_arg(va,
long long);
726 idx =
_ntoa_long_long(out, buffer, idx, maxlen, (
unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
730 const long value = va_arg(va,
long);
731 idx =
_ntoa_long(out, buffer, idx, maxlen, (
unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
734 const int value = (flags &
FLAGS_CHAR) ? (
signed char)va_arg(va,
int) : (flags &
FLAGS_SHORT) ? (
short int)va_arg(va,
int) : va_arg(va,
int);
735 idx =
_ntoa_long(out, buffer, idx, maxlen, (
unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
741 #if defined(PRINTF_SUPPORT_LONG_LONG)
742 idx =
_ntoa_long_long(out, buffer, idx, maxlen, va_arg(va,
unsigned long long),
false, base, precision, width, flags);
746 idx =
_ntoa_long(out, buffer, idx, maxlen, va_arg(va,
unsigned long),
false, base, precision, width, flags);
749 const unsigned int value = (flags &
FLAGS_CHAR) ? (
unsigned char)va_arg(va,
unsigned int) : (flags &
FLAGS_SHORT) ? (
unsigned short int)va_arg(va,
unsigned int) : va_arg(va,
unsigned int);
750 idx =
_ntoa_long(out, buffer, idx, maxlen, value,
false, base, precision, width, flags);
756 #if defined(PRINTF_SUPPORT_FLOAT)
760 idx =
_ftoa(out, buffer, idx, maxlen, va_arg(va,
double), precision, width, flags);
763 #if defined(PRINTF_SUPPORT_EXPONENTIAL)
770 idx =
_etoa(out, buffer, idx, maxlen, va_arg(va,
double), precision, width, flags);
773 #endif // PRINTF_SUPPORT_EXPONENTIAL
774 #endif // PRINTF_SUPPORT_FLOAT
779 while (l++ < width) {
780 out(
' ', buffer, idx++, maxlen);
784 out((
char)va_arg(va,
int), buffer, idx++, maxlen);
787 while (l++ < width) {
788 out(
' ', buffer, idx++, maxlen);
796 const char* p = va_arg(va,
char*);
797 unsigned int l =
_strnlen_s(p, precision ? precision : (
size_t)-1);
800 l = (l < precision ? l : precision);
803 while (l++ < width) {
804 out(
' ', buffer, idx++, maxlen);
809 out(*(p++), buffer, idx++, maxlen);
813 while (l++ < width) {
814 out(
' ', buffer, idx++, maxlen);
822 width =
sizeof(
void*) * 2U;
824 #if defined(PRINTF_SUPPORT_LONG_LONG)
825 const bool is_ll =
sizeof(uintptr_t) ==
sizeof(
long long);
827 idx =
_ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va,
void*),
false, 16U, precision, width, flags);
831 idx =
_ntoa_long(out, buffer, idx, maxlen, (
unsigned long)((uintptr_t)va_arg(va,
void*)),
false, 16U, precision, width, flags);
832 #if defined(PRINTF_SUPPORT_LONG_LONG)
840 out(
'%', buffer, idx++, maxlen);
845 out(*format, buffer, idx++, maxlen);
852 out((
char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
864 va_start(va, format);
872 int sprintf_(
char* buffer,
const char* format, ...)
875 va_start(va, format);
882 int snprintf_(
char* buffer,
size_t count,
const char* format, ...)
885 va_start(va, format);
899 int vsnprintf_(
char* buffer,
size_t count,
const char* format, va_list va)
905 int fctprintf(
void (*out)(
char character,
void* arg),
void* arg,
const char* format, ...)
908 va_start(va, format);
910 const int ret =
_vsnprintf(
_out_fct, (
char*)(uintptr_t)&out_fct_wrap, (
size_t)-1, format, va);
915 int fctvprintf(
void (*out)(
char character,
void* arg),
void* arg,
const char* format, va_list va)