6 #define FL_LEFTADJUST 0x0001U
7 #define FL_SIGN 0x0002U
8 #define FL_ZEROPAD 0x0004U
9 #define FL_ALTERNATE 0x0008U
10 #define FL_SPACE 0x0010U
11 #define FL_SHORT 0x0020U
12 #define FL_LONG 0x0040U
13 #define FL_LONGDOUBLE 0x0080U
14 #define FL_POINTER 0x0100U
16 #define MAX_WIDTH ((SHRT_MAX - 9) / 10)
21 #define BUFFER_LEN 1000
23 #define PUTSTR(szPutStr, iPutLen) \
26 if (iOutFoo(pvOutData, (const char*)szPutStr, (size_t)iPutLen) < 0) \
28 iOutCount += iPutLen; \
31 #define PAD(szPadStr, iPadLen) \
38 if (iOutFoo(pvOutData, (const char*)szPadStr, 32) < 0) \
45 if (iOutFoo(pvOutData, (const char*)szPadStr, (size_t)iTmp) < 0) \
52 #define PADSPACES(iPadWidth) PAD(szSpaces, iPadWidth)
53 #define PADZEROS(iPadWidth) PAD(szZeros, iPadWidth)
55 static const char szSpaces[] =
" ";
56 static const char szZeros[] =
"00000000000000000000000000000000";
68 #ifndef OUTFMT_NO_FLOAT
76 static const int iEndianChk = 1;
78 #define iIsBigEndian() (*(char*)&iEndianChk == 0)
80 #define iIsNanOrInf(puVal) \
82 sizeof((*puVal).dVal) == sizeof((*puVal).aul) \
86 (((*puVal).aul[0] & 0x7ff00000UL) == 0x7ff00000UL) \
88 (((*puVal).aul[0] & 0x000fffffUL) || (*puVal).aul[1]) \
90 ((*puVal).aul[0] & 0x80000000UL) \
94 ((*puVal).aul[0] & 0x80000000UL) \
99 (((*puVal).aul[1] & 0x7ff00000UL) == 0x7ff00000UL) \
101 (((*puVal).aul[1] & 0x000fffffUL) || (*puVal).aul[0]) \
103 ((*puVal).aul[1] & 0x80000000UL) \
107 ((*puVal).aul[1] & 0x80000000UL) \
116 static int _vsOutFmt(
int (*iOutFoo)(
void* pvOutData,
const char*,
size_t),
124 unsigned int uiFlags;
125 int iWidth, iPrec, iPrefixLen, iLeadingZeros, iTmp;
128 const char* szPrefix;
135 while (*szFmt !=
'\0' && *szFmt !=
'%')
137 iStrLen = (int)(szFmt - szStr);
143 iStrLen = iPrefixLen = 0;
146 while ((*szFmt ==
'-') || (*szFmt ==
'+') || (*szFmt ==
'0') || (*szFmt ==
'#') || (*szFmt ==
' '))
174 iWidth = va_arg(tArg,
int);
183 for (iWidth = 0; (*szFmt >=
'0') && (*szFmt <=
'9'); szFmt++)
186 iWidth = iWidth * 10 + (*szFmt -
'0');
196 iPrec = va_arg(tArg,
int);
202 for (iPrec = 0; (*szFmt >=
'0') && (*szFmt <=
'9'); szFmt++)
204 iPrec = iPrec * 10 + (*szFmt -
'0');
236 iWidth =
sizeof(
void*) * 2;
245 unsigned long ulValue;
246 char* pcChar = (
char*)&aucBuffer[(
sizeof aucBuffer) - 1];
250 ulValue = (
unsigned long)va_arg(tArg,
void*);
252 ulValue = (
unsigned long)va_arg(tArg,
long);
254 ulValue = (
unsigned long)va_arg(tArg,
int);
257 if (iPrec == 0 && ulValue == 0)
263 if (*szFmt ==
'd' || *szFmt ==
'i')
265 if ((
long)ulValue < 0)
267 ulValue = -(long)ulValue;
283 int iChar = ulValue % 10U;
285 *--pcChar = (char)(
'0' + iChar);
291 const unsigned uiRadix = (*szFmt ==
'u')
293 : (*szFmt ==
'o') ? 8U : 16U;
294 const char* acDigits = (*szFmt ==
'X')
296 :
"0123456789abcdef";
299 ulValue &= USHRT_MAX;
303 *--pcChar = acDigits[ulValue % uiRadix];
314 else if (*szFmt ==
'X')
319 else if (*szFmt ==
'x')
330 iLeadingZeros = iStrLen < iPrec ? iPrec - iStrLen : 0;
334 iTmp = iWidth - iPrefixLen - iLeadingZeros - iStrLen;
336 iLeadingZeros += iTmp;
339 iWidth -= iPrefixLen + iLeadingZeros + iStrLen;
343 PUTSTR(szPrefix, iPrefixLen);
357 #ifdef OUTFMT_NO_FLOAT
358 szStr =
"(no float support)";
363 ? (
double)va_arg(tArg,
long double)
364 : va_arg(tArg,
double);
367 double dValue = va_arg(tArg,
double);
369 int iDecZeros, iExpZeros, iDecPoint, iFracDigs;
370 int iTrailZeros, iExpLen, iExp, iSavedPrec;
371 char *szFrac, *szExp;
373 static const char* szNanInf[] = {
"-NaN",
"NaN",
376 iDecZeros = iExpZeros = iFracDigs = 0;
377 iTrailZeros = iExpLen = iExp = 0;
384 szStr = szNanInf[iTmp - 1];
409 while (dValue >= 1e64)
414 while (dValue >= 1e32)
419 while (dValue >= 1e16)
425 while (dValue >= 1e08)
430 while (dValue >= 1e04)
435 while (dValue >= 1e01)
441 else if (dValue < 1.0 && dValue > 0.0)
445 while (dValue < 1e-63)
450 while (dValue < 1e-31)
455 while (dValue < 1e-15)
461 while (dValue < 1e-7)
466 while (dValue < 1e-3)
471 while (dValue < 1e-0)
484 iPrec = iSavedPrec = 6;
486 if (cFmt ==
'g' || cFmt ==
'G')
488 if (iExp < -4 || iExp >= iPrec)
490 cFmt = (char)(cFmt ==
'g' ?
'e' :
'E');
510 szStr = (
char*)aucBuffer;
512 if (cFmt ==
'e' || cFmt ==
'E')
515 aucBuffer[iStrLen++] = (
unsigned char)(iTmp +
'0');
521 aucBuffer[iStrLen++] =
'0';
527 iExpZeros = iExp - (
DBL_DIG + 1);
534 aucBuffer[iStrLen++] = (
unsigned char)(iTmp +
'0');
540 szFrac = (
char*)&aucBuffer[iStrLen];
543 while (iDecZeros < iPrec && iExp < -1)
552 while (iFracDigs + iDecZeros < iPrec && iStrLen + iFracDigs <
DBL_DIG + 1)
555 szFrac[iFracDigs++] = (char)(iTmp +
'0');
561 if (!iFracDigs && iDecZeros)
563 szFrac[iFracDigs++] = (char)
'0';
567 if (dValue >= 5.0 && (iFracDigs || !iPrec))
569 iTmp = iStrLen + iFracDigs - 1;
570 while (aucBuffer[iTmp] ==
'9' && iTmp >= 0)
571 aucBuffer[iTmp--] =
'0';
572 if (iTmp == 0 && iDecZeros)
574 for (iTmp = iStrLen + iFracDigs - 1;
578 aucBuffer[iTmp] = aucBuffer[iTmp - 1];
587 if (iPrec + 1 + iExp >= 0)
592 else if (iPrec == 0 || iFracDigs == iPrec)
601 aucBuffer[iStrLen + iFracDigs] =
'0';
604 if (iStrLen >= iSavedPrec && (*szFmt ==
'g' || *szFmt ==
'G'))
606 cFmt = (char)(*szFmt ==
'g' ?
'e' :
'E');
619 if (*szFmt ==
'g' || *szFmt ==
'G')
627 iTmp = iStrLen + iFracDigs - 1;
628 while (aucBuffer[iTmp--] ==
'0' && iFracDigs > 0)
635 iDecPoint = iFracDigs ? 1 : 0;
642 iTrailZeros = iPrec - iFracDigs - iDecZeros;
648 if (cFmt ==
'e' || cFmt ==
'E')
650 szExp = &szFrac[iFracDigs];
651 szExp[iExpLen++] = cFmt;
652 szExp[iExpLen++] = (char)((iExp < 0)
656 #ifndef OUTFMT_LONG_EXP
660 szExp[iExpLen++] = (char)(iExp / 100 +
'0');
663 szExp[iExpLen++] = (char)(iExp / 10 +
'0');
664 szExp[iExpLen++] = (char)(iExp % 10 +
'0');
668 #ifdef OUTFMT_NO_MINUS_ZERO
669 if ((iPrefixLen == 1 && *szPrefix ==
'-') && (iStrLen == 1 && *szStr ==
'0') && ((iFracDigs == 1 && *szFrac ==
'0') || iFracDigs == 0))
679 iLeadingZeros = iWidth - (iPrefixLen + iStrLen + iExpZeros + iDecPoint + iDecZeros + iFracDigs + iTrailZeros + iExpLen);
680 if (iLeadingZeros < 0)
686 iWidth -= iPrefixLen + iLeadingZeros + iStrLen + iExpZeros + iDecPoint + iDecZeros + iFracDigs + iTrailZeros + iExpLen;
690 PUTSTR(szPrefix, iPrefixLen);
696 PUTSTR(szFrac, iFracDigs);
706 aucBuffer[0] = (
unsigned char)va_arg(tArg,
int);
707 szStr = (
char*)aucBuffer;
712 String* str = va_arg(tArg, String*);
719 szStr = str->c_str();
724 szStr = va_arg(tArg,
char*);
729 while (szStr[iStrLen] !=
'\0')
731 if (iPrec >= 0 && iPrec < iStrLen)
740 *va_arg(tArg,
short*) = (short)iOutCount;
742 *va_arg(tArg,
long*) = (long)iOutCount;
744 *va_arg(tArg,
int*) = (int)iOutCount;
748 aucBuffer[0] = (
unsigned char)*szFmt;
749 szStr = (
char*)aucBuffer;
767 if (iOutFoo(pvOutData, NULL, 0) < 0)
772 static bool sFormatString_init;
773 static bool sFormatString_PSRam;
776 snprintfOut(
void* ps,
const char* szStr,
size_t tLen)
778 SSnprintf* psSnprintf = (SSnprintf*)ps;
780 if (szStr == NULL && tLen == 0)
782 if (psSnprintf->tRoomFor)
784 *psSnprintf->cpBuf =
'\0';
791 if (psSnprintf->tGrow && psSnprintf->tRoomFor <= tLen)
793 size_t growsize = (tLen - psSnprintf->tRoomFor) + 64;
794 psSnprintf->tBufSize += growsize;
795 size_t usedsize = psSnprintf->cpBuf - psSnprintf->cpBuffer;
796 psSnprintf->cpBuffer = (sFormatString_PSRam) ?
797 (
char*)ps_realloc(psSnprintf->cpBuffer, psSnprintf->tBufSize) :
798 (char*)realloc(psSnprintf->cpBuffer, psSnprintf->tBufSize);
799 psSnprintf->cpBuf = psSnprintf->cpBuffer + usedsize;
800 psSnprintf->tRoomFor += growsize;
802 while (psSnprintf->tRoomFor > 1 && tLen > 0)
804 psSnprintf->tRoomFor--;
806 *psSnprintf->cpBuf++ = *szStr++;
810 *psSnprintf->cpBuf =
'\0';
822 ssnprintf.tBufSize = 64;
823 if (!sFormatString_init)
825 sFormatString_PSRam = psramInit();
826 sFormatString_init =
true;
828 ssnprintf.cpBuf = ssnprintf.cpBuffer = (sFormatString_PSRam) ?
829 (
char*)ps_malloc(ssnprintf.tBufSize) : (
char*)malloc(ssnprintf.tBufSize);
830 ssnprintf.tRoomFor = ssnprintf.tBufSize;
831 ssnprintf.tGrow =
true;
833 iOutCnt = _vsOutFmt(snprintfOut, (
void*)&ssnprintf, szFmt, tArg);
834 *acBuf = ssnprintf.cpBuffer;