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) 122 typedef void (*
out_fct_type)(
char character,
void* buffer,
size_t idx,
size_t maxlen);
127 void (*fct)(
char character,
void* arg);
133 static inline void _out_buffer(
char character,
void* buffer,
size_t idx,
size_t maxlen)
136 ((
char*)buffer)[idx] = character;
142 static inline void _out_null(
char character,
void* buffer,
size_t idx,
size_t maxlen)
144 (void)character; (void)buffer; (void)idx; (void)maxlen;
149 static inline void _out_char(
char character,
void* buffer,
size_t idx,
size_t maxlen)
151 (void)buffer; (void)idx; (void)maxlen;
159 static inline void _out_fct(
char character,
void* buffer,
size_t idx,
size_t maxlen)
161 (void)idx; (void)maxlen;
171 static inline unsigned int _strnlen_s(
const char* str,
size_t maxsize)
174 for (s = str; *s && maxsize--; ++s);
175 return (
unsigned int)(s - str);
183 return (ch >=
'0') && (ch <=
'9');
188 static unsigned int _atoi(
const char** str)
192 i = i * 10U + (
unsigned int)(*((*str)++) -
'0');
199 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)
201 const size_t start_idx = idx;
205 for (
size_t i = len; i < width; i++) {
206 out(
' ', buffer, idx++, maxlen);
212 out(buf[--len], buffer, idx++, maxlen);
216 if (flags & FLAGS_LEFT) {
217 while (idx - start_idx < width) {
218 out(
' ', buffer, idx++, maxlen);
227 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)
244 if (!(flags &
FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
246 if (len && (base == 16U)) {
276 return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
281 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)
294 const char digit = (char)(value % base);
295 buf[len++] = digit < 10 ?
'0' + digit : (flags &
FLAGS_UPPERCASE ?
'A' :
'a') + digit - 10;
300 return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (
unsigned int)base, prec, width, flags);
305 #if defined(PRINTF_SUPPORT_LONG_LONG) 306 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)
319 const char digit = (char)(value % base);
320 buf[len++] = digit < 10 ?
'0' + digit : (flags &
FLAGS_UPPERCASE ?
'A' :
'a') + digit - 10;
325 return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (
unsigned int)base, prec, width, flags);
327 #endif // PRINTF_SUPPORT_LONG_LONG 330 #if defined(PRINTF_SUPPORT_FLOAT) 332 #if defined(PRINTF_SUPPORT_EXPONENTIAL) 334 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);
339 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)
346 static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
350 return _out_rev(out, buffer, idx, maxlen,
"nan", 3, width, flags);
351 if (value < -DBL_MAX)
352 return _out_rev(out, buffer, idx, maxlen,
"fni-", 4, width, flags);
354 return _out_rev(out, buffer, idx, maxlen, (flags &
FLAGS_PLUS) ?
"fni+" :
"fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
359 #if defined(PRINTF_SUPPORT_EXPONENTIAL) 360 return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
367 bool negative =
false;
383 int whole = (int)value;
384 double tmp = (value - whole) * pow10[prec];
385 unsigned long frac = (
unsigned long)tmp;
391 if (frac >= pow10[prec]) {
396 else if (diff < 0.5) {
398 else if ((frac == 0U) || (frac & 1U)) {
404 diff = value - (double)whole;
405 if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
412 unsigned int count = prec;
416 buf[len++] = (char)(48U + (frac % 10U));
417 if (!(frac /= 10U)) {
433 buf[len++] = (char)(48 + (whole % 10));
434 if (!(whole /= 10)) {
441 if (width && (negative || (flags & (FLAGS_PLUS |
FLAGS_SPACE)))) {
453 else if (flags & FLAGS_PLUS) {
461 return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
465 #if defined(PRINTF_SUPPORT_EXPONENTIAL) 467 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)
470 if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
471 return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
475 const bool negative = value < 0;
493 int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023;
494 conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U);
496 int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
498 exp2 = (int)(expval * 3.321928094887362 + 0.5);
499 const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
500 const double z2 = z * z;
501 conv.U = (uint64_t)(exp2 + 1023) << 52U;
503 conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
505 if (value < conv.F) {
511 unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
516 if ((value >= 1e-4) && (value < 1e6)) {
517 if ((
int)prec > expval) {
518 prec = (unsigned)((
int)prec - expval - 1);
537 unsigned int fwidth = width;
538 if (width > minwidth) {
556 const size_t start_idx = idx;
557 idx =
_ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
566 if (flags & FLAGS_LEFT) {
567 while (idx - start_idx < width) out(
' ', buffer, idx++, maxlen);
572 #endif // PRINTF_SUPPORT_EXPONENTIAL 573 #endif // PRINTF_SUPPORT_FLOAT 579 unsigned int flags, width, precision, n;
590 if (*format !=
'%') {
592 out(*format, buffer, idx++, maxlen);
606 case '-': flags |=
FLAGS_LEFT; format++; n = 1U;
break;
607 case '+': flags |=
FLAGS_PLUS; format++; n = 1U;
break;
608 case ' ': flags |=
FLAGS_SPACE; format++; n = 1U;
break;
609 case '#': flags |=
FLAGS_HASH; format++; n = 1U;
break;
610 default : n = 0U;
break;
617 width =
_atoi(&format);
619 else if (*format ==
'*') {
620 const int w = va_arg(va,
int);
623 width = (
unsigned int)-w;
626 width = (
unsigned int)w;
633 if (*format ==
'.') {
637 precision =
_atoi(&format);
639 else if (*format ==
'*') {
640 const int prec = (int)va_arg(va,
int);
641 precision = prec > 0 ? (
unsigned int)prec : 0U;
651 if (*format ==
'l') {
659 if (*format ==
'h') {
664 #if defined(PRINTF_SUPPORT_PTRDIFF_T) 693 if (*format ==
'x' || *format ==
'X') {
696 else if (*format ==
'o') {
699 else if (*format ==
'b') {
707 if (*format ==
'X') {
712 if ((*format !=
'i') && (*format !=
'd')) {
722 if ((*format ==
'i') || (*format ==
'd')) {
725 #if defined(PRINTF_SUPPORT_LONG_LONG) 726 const long long value = va_arg(va,
long long);
727 idx =
_ntoa_long_long(out, buffer, idx, maxlen, (
unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
731 const long value = va_arg(va,
long);
732 idx =
_ntoa_long(out, buffer, idx, maxlen, (
unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
735 const int value = (flags &
FLAGS_CHAR) ? (
char)va_arg(va,
int) : (flags &
FLAGS_SHORT) ? (
short int)va_arg(va,
int) : va_arg(va,
int);
736 idx =
_ntoa_long(out, buffer, idx, maxlen, (
unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
742 #if defined(PRINTF_SUPPORT_LONG_LONG) 743 idx =
_ntoa_long_long(out, buffer, idx, maxlen, va_arg(va,
unsigned long long),
false, base, precision, width, flags);
747 idx =
_ntoa_long(out, buffer, idx, maxlen, va_arg(va,
unsigned long),
false, base, precision, width, flags);
750 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);
751 idx =
_ntoa_long(out, buffer, idx, maxlen, value,
false, base, precision, width, flags);
757 #if defined(PRINTF_SUPPORT_FLOAT) 761 idx =
_ftoa(out, buffer, idx, maxlen, va_arg(va,
double), precision, width, flags);
764 #if defined(PRINTF_SUPPORT_EXPONENTIAL) 771 idx =
_etoa(out, buffer, idx, maxlen, va_arg(va,
double), precision, width, flags);
774 #endif // PRINTF_SUPPORT_EXPONENTIAL 775 #endif // PRINTF_SUPPORT_FLOAT 780 while (l++ < width) {
781 out(
' ', buffer, idx++, maxlen);
785 out((
char)va_arg(va,
int), buffer, idx++, maxlen);
787 if (flags & FLAGS_LEFT) {
788 while (l++ < width) {
789 out(
' ', buffer, idx++, maxlen);
797 const char* p = va_arg(va,
char*);
798 unsigned int l =
_strnlen_s(p, precision ? precision : (
size_t)-1);
801 l = (l < precision ? l : precision);
804 while (l++ < width) {
805 out(
' ', buffer, idx++, maxlen);
809 while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
810 out(*(p++), buffer, idx++, maxlen);
813 if (flags & FLAGS_LEFT) {
814 while (l++ < width) {
815 out(
' ', buffer, idx++, maxlen);
823 width =
sizeof(
void*) * 2U;
825 #if defined(PRINTF_SUPPORT_LONG_LONG) 826 const bool is_ll =
sizeof(uintptr_t) ==
sizeof(
long long);
828 idx =
_ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va,
void*),
false, 16U, precision, width, flags);
832 idx =
_ntoa_long(out, buffer, idx, maxlen, (
unsigned long)((uintptr_t)va_arg(va,
void*)),
false, 16U, precision, width, flags);
833 #if defined(PRINTF_SUPPORT_LONG_LONG) 841 out(
'%', buffer, idx++, maxlen);
846 out(*format, buffer, idx++, maxlen);
853 out((
char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
865 va_start(va, format);
873 int sprintf_(
char* buffer,
const char* format, ...)
876 va_start(va, format);
886 va_start(va, format);
906 int fctprintf(
void (*out)(
char character,
void* arg),
void* arg,
const char* format, ...)
909 va_start(va, format);
911 const int ret =
_vsnprintf(
_out_fct, (
char*)(uintptr_t)&out_fct_wrap, (
size_t)-1, format, va);
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)
static void _out_fct(char character, void *buffer, size_t idx, size_t maxlen)
static bool _is_digit(char ch)
static unsigned int _strnlen_s(const char *str, size_t maxsize)
int vprintf_(const char *format, va_list va)
GeneratorWrapper< T > value(T &&value)
size_t count(InputIterator first, InputIterator last, T const &item)
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)
#define PRINTF_FTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE
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)
void _putchar(char character)
int fctprintf(void(*out)(char character, void *arg), void *arg, const char *format,...)
int sprintf_(char *buffer, const char *format,...)
#define PRINTF_DEFAULT_FLOAT_PRECISION
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)
static unsigned int _atoi(const char **str)
static void _out_buffer(char character, void *buffer, size_t idx, size_t maxlen)
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)
static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, const char *format, va_list va)
void(* out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen)
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)
int printf_(const char *format,...)
int vsnprintf_(char *buffer, size_t count, const char *format, va_list va)
static void _out_char(char character, void *buffer, size_t idx, size_t maxlen)
static void _out_null(char character, void *buffer, size_t idx, size_t maxlen)
int snprintf_(char *buffer, size_t count, const char *format,...)