/** * Copyright 2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 #define OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 #define SECUREC_NULL_STRING_SIZE 8 #define SECUREC_STATE_TABLE_SIZE 337 #define SECUREC_OFFSET_BITS_WORD 16 #define SECUREC_OFFSET_BITS_DWORD 32 #define SECUREC_OFFSET_DIV_OCTAL 3 #define SECUREC_OFFSET_DIV_HEX 4 #define SECUREC_RADIX_OCTAL 8 #define SECUREC_RADIX_DECIMAL 10 #define SECUREC_RADIX_HEX 16 /* Use two displacements to eliminate compilation warnings */ #define SECUREC_SHR_DWORD(x) (((x) >> 16) >> 16) #define SECUREC_PREFIX_LEN 2 /* size include '+' and '\0' */ #define SECUREC_FLOAT_BUF_EXT 2 #ifdef SECUREC_STACK_SIZE_LESS_THAN_1K #define SECUREC_FMT_STR_LEN 8 #else #define SECUREC_FMT_STR_LEN 16 #endif typedef struct { unsigned int flags; int fldWidth; int precision; int bufferIsWide; /* flag for buffer contains wide chars ;0 is not wide char */ int dynWidth; /* %* 1 width from variable parameter ;0 not */ int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ } SecFormatAttr; typedef union { char *str; /* not a null terminated string */ #if SECUREC_HAVE_WCHART wchar_t *wStr; #endif } SecFormatBuf; typedef union { char str[SECUREC_BUFFER_SIZE + 1]; #ifdef SECUREC_FOR_WCHAR wchar_t wStr[SECUREC_BUFFER_SIZE + 1]; #endif } SecBuffer; #if SECUREC_ENABLE_SPRINTF_FLOAT /* call system sprintf to format float value */ static int SecIndirectSprintf(char *strDest, const char *format, ...) { int ret; /* If initialization causes e838 */ va_list argList; va_start(argList, format); SECUREC_MASK_MSVC_CRT_WARNING ret = vsprintf(strDest, format, argList); SECUREC_END_MASK_MSVC_CRT_WARNING va_end(argList); (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT /* out put long double value to dest */ static int SecFormatLongDboule(char *strDest,const SecFormatAttr *formatAttr, const char *fmt, long double ldValue) { int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth); if (formatAttr->dynWidth && formatAttr->dynPrecision) { return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, ldValue); } else if (formatAttr->dynWidth) { return SecIndirectSprintf(strDest, fmt, fldWidth, ldValue); } else if (formatAttr->dynPrecision) { return SecIndirectSprintf(strDest, fmt, formatAttr->precision, ldValue); } return SecIndirectSprintf(strDest, fmt, ldValue); } #endif /* out put double value to dest */ static int SecFormatDboule(char *strDest, const SecFormatAttr *formatAttr, const char *fmt, double dValue) { int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth); if (formatAttr->dynWidth && formatAttr->dynPrecision) { return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, dValue); } else if (formatAttr->dynWidth) { return SecIndirectSprintf(strDest, fmt, fldWidth, dValue); } else if (formatAttr->dynPrecision) { return SecIndirectSprintf(strDest, fmt, formatAttr->precision, dValue); } return SecIndirectSprintf(strDest, fmt, dValue); } #endif #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT /* to clear e506 warning */ static int SecIsSameSize(size_t sizeA, size_t sizeB) { return sizeA == sizeB; } #endif #define SECUREC_SPECIAL_DWORD(val32, numBase) do { \ --formatBuf.str; \ *(formatBuf.str) = digits[(val32) % (numBase)]; \ } while (((val32) /= (numBase)) != 0) #if defined(SECUREC_USE_SPECIAL_DIV64) || (defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)) /* * Fast divide by 10 algorithm. * Calculation divisor multiply 0xcccccccccccccccdULL, resultHi64 >> 3 as quotient */ static void SecU64Div10(SecUnsignedInt64 divisor, SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder) { SecUnsignedInt64 mask = 0xffffffffULL; /* use 0xffffffffULL as 32 bit mask */ SecUnsignedInt64 magicHi = 0xccccccccULL; /* fast divide 10 magic numbers high 32bit 0xccccccccULL */ SecUnsignedInt64 magicLow = 0xcccccccdULL; /* fast divide 10 magic numbers low 32bit 0xcccccccdULL */ SecUnsignedInt64 divisorHi = (SecUnsignedInt64)(SECUREC_SHR_DWORD(divisor)); /* hig 32 bit use */ SecUnsignedInt64 divisorLow = (SecUnsignedInt64)(divisor & mask); /* low 32 bit mask */ SecUnsignedInt64 factorHi = divisorHi * magicHi; SecUnsignedInt64 factorLow1 = divisorHi * magicLow; SecUnsignedInt64 factorLow2 = divisorLow * magicHi; SecUnsignedInt64 factorLow3 = divisorLow * magicLow; SecUnsignedInt64 carry = (factorLow1 & mask) + (factorLow2 & mask) + SECUREC_SHR_DWORD(factorLow3); SecUnsignedInt64 resultHi64 = factorHi + SECUREC_SHR_DWORD(factorLow1) + \ SECUREC_SHR_DWORD(factorLow2) + SECUREC_SHR_DWORD(carry); *quotient = resultHi64 >> 3; /* fast divide 10 magic numbers 3 */ *remainder = (SecUnsignedInt32)(divisor - ((*quotient) * 10)); /* quotient mul 10 */ return; } #if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) /* * Divide function for VXWORKS */ static int SecU64Div32(SecUnsignedInt64 divisor, SecUnsignedInt32 radix, SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder) { switch (radix) { case SECUREC_RADIX_DECIMAL: SecU64Div10(divisor, quotient, remainder); break; case SECUREC_RADIX_HEX: *quotient = divisor >> SECUREC_OFFSET_DIV_HEX; *remainder = divisor & 0xfULL; /* mask one hex number by 0xfULL */ break; case SECUREC_RADIX_OCTAL: *quotient = divisor >> SECUREC_OFFSET_DIV_OCTAL; *remainder = divisor & 0x7ULL; /* mask one hex number by 0x7ULL */ break; default: return -1; } return 0; } #endif #endif #if defined(SECUREC_USE_SPECIAL_DIV64) /* The compiler does not provide 64 bit division problems */ #define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \ SecUnsignedInt64 quotient = 0; \ SecUnsignedInt32 digit = 0; \ SecU64Div10((val64), &(quotient), &(digit)); \ --formatBuf.str; \ *(formatBuf.str) = digits[digit]; \ (val64) = quotient; \ } while ((val64) != 0) #else #define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \ --formatBuf.str; \ *(formatBuf.str) = digits[(val64) % SECUREC_RADIX_DECIMAL]; \ } while (((val64) /= SECUREC_RADIX_DECIMAL) != 0) #endif #define SECUREC_SPECIAL_QWORD(val64, numBase) do { \ --formatBuf.str; \ *(formatBuf.str) = digits[(val64) % (numBase)]; \ } while (((val64) /= (numBase)) != 0) #define SECUREC_SAFE_WRITE_STR_OPT(src, txtLen, outStream, outChars) do { \ int ii_; \ for (ii_ = 0; ii_ < (txtLen); ++ii_) { \ *((SecChar *)(void *)((outStream)->cur)) = *(SecChar *)(src); \ (outStream)->cur += sizeof(SecChar); \ (src) = (src) + 1; \ } \ (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \ *(outChars) = *(outChars) + (txtLen); \ } SECUREC_WHILE_ZERO #define SECUREC_SAFE_WRITE_STR(src, txtLen, outStream, outChars) do { \ if ((txtLen) < 12) { /* performance optimization for mobile number length 12 */ \ SECUREC_SAFE_WRITE_STR_OPT((src), (txtLen), (outStream), (outChars)); \ } else { \ SecDoMemcpy((outStream)->cur, (src), ((size_t)(unsigned int)(txtLen) * (sizeof(SecChar)))); \ (outStream)->cur += (size_t)((size_t)(unsigned int)(txtLen) * (sizeof(SecChar))); \ (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \ *(outChars) = *(outChars) + (txtLen); \ } \ } SECUREC_WHILE_ZERO #define SECUREC_SAFE_WRITE_CHAR(c, outStream, outChars) do { \ *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(c); \ (outStream)->cur += sizeof(SecChar); \ (outStream)->count -= (int)(sizeof(SecChar)); \ *(outChars) = *(outChars) + 1; \ } SECUREC_WHILE_ZERO #define SECUREC_SAFE_PADDING(padChar, padLen, outStream, outChars) do { \ int ii_; \ for (ii_ = 0; ii_ < (padLen); ++ii_) { \ *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(padChar); \ (outStream)->cur += sizeof(SecChar); \ } \ (outStream)->count -= (padLen) * (int)(sizeof(SecChar)); \ *(outChars) = *(outChars) + (padLen); \ } SECUREC_WHILE_ZERO /* The count variable can be reduced to 0, and the external function complements the \0 terminator. */ #define SECUREC_IS_REST_BUF_ENOUGH(stream, needLen) ((int)((stream)->count - \ (int)(needLen) * (int)(sizeof(SecChar))) >= 0) #define SECUREC_FMT_STATE_OFFSET 256 #ifdef SECUREC_FOR_WCHAR #define SECUREC_FMT_TYPE(c, fmtTable) ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \ ((fmtTable)[(unsigned char)(c)]) : 0) #define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)((((fmtTable)[(SECUREC_FMT_TYPE(c, (fmtTable))) * \ ((unsigned char)STAT_INVALID + 1) + \ (unsigned char)(lastState) + \ SECUREC_FMT_STATE_OFFSET]))) #else #define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)(((fmtTable)[((fmtTable)[(unsigned char)(c)]) * \ ((unsigned char)STAT_INVALID + 1) + \ (unsigned char)(lastState) + \ SECUREC_FMT_STATE_OFFSET])) #endif static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) { switch (ch) { case SECUREC_CHAR(' '): attr->flags |= SECUREC_FLAG_SIGN_SPACE; break; case SECUREC_CHAR('+'): attr->flags |= SECUREC_FLAG_SIGN; break; case SECUREC_CHAR('-'): attr->flags |= SECUREC_FLAG_LEFT; break; case SECUREC_CHAR('0'): attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */ break; case SECUREC_CHAR('#'): attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */ break; default: break; } return; } /* * Decoded size identifier in format string to Reduce the number of lines of function code */ static int SecDecodeSizeI(SecFormatAttr *attr, const SecChar **format) { #ifdef SECUREC_ON_64BITS attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */ #endif if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) { (*format) += 2; /* add 2 to skip I64 */ attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */ } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) { (*format) += 2; /* add 2 to skip I32 */ attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */ } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) || (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) { /* do nothing */ } else { /* Compatibility code for "%I" just print I */ return -1; } return 0; } /* * Decoded size identifier in format string */ static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) { switch (ch) { #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT case SECUREC_CHAR('j'): attr->flags |= SECUREC_FLAG_INTMAX; break; #endif case SECUREC_CHAR('q'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('L'): attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE; break; case SECUREC_CHAR('l'): if (**format == SECUREC_CHAR('l')) { *format = *format + 1; attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */ } else { attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */ } break; case SECUREC_CHAR('t'): attr->flags |= SECUREC_FLAG_PTRDIFF; break; #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT case SECUREC_CHAR('z'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('Z'): attr->flags |= SECUREC_FLAG_SIZE; break; #endif case SECUREC_CHAR('I'): if (SecDecodeSizeI(attr, format) != 0) { /* Compatibility code for "%I" just print I */ return -1; } break; case SECUREC_CHAR('h'): if (**format == SECUREC_CHAR('h')) { attr->flags |= SECUREC_FLAG_CHAR; /* char */ } else { attr->flags |= SECUREC_FLAG_SHORT; /* short int */ } break; case SECUREC_CHAR('w'): attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */ break; default: break; } return 0; } /* * Decoded char type identifier */ static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS)) attr->flags &= ~SECUREC_FLAG_LEADZERO; #endif #ifdef SECUREC_FOR_WCHAR attr->bufferIsWide = 1; if (attr->flags & SECUREC_FLAG_SHORT) { #if SECUREC_HAVE_MBTOWC /* multibyte character to wide character */ char tmpChar[2]; /* One character string, length is 2 */ tmpChar[0] = (char)(cValue & 0x00ff); tmpChar[1] = '\0'; if (mbtowc(buffer->wStr, tmpChar, sizeof(tmpChar)) < 0) { return -1; } #else return -1; #endif } else { buffer->wStr[0] = (wchar_t)cValue; } formatBuf->wStr = buffer->wStr; return 1; /* only 1 wide character */ #else /* SECUREC_FOR_WCHAR */ attr->bufferIsWide = 0; if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { #if SECUREC_HAVE_WCTOMB wchar_t wChar = (wchar_t)cValue; int textLen; /* wide character to multibyte character */ SECUREC_MASK_MSVC_CRT_WARNING textLen = wctomb(buffer->str, wChar); SECUREC_END_MASK_MSVC_CRT_WARNING if (textLen < 0) { return -1; } formatBuf->str = buffer->str; return textLen; #else return -1; #endif } else { /* get multibyte character from argument */ unsigned short temp; temp = (unsigned short)cValue; buffer->str[0] = (char)temp; formatBuf->str = buffer->str; return 1; /* only 1 character */ } #endif } /* literal string to print null ptr, define it as array rather than const text area * is to avoid gcc warning with pointing const text with variable */ #if SECUREC_HAVE_WCHART static wchar_t g_wStrNullString[SECUREC_NULL_STRING_SIZE] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; #endif static char g_strNullString[SECUREC_NULL_STRING_SIZE] = "(null)"; static int SecDecodeTypeSchar(const SecFormatAttr *attr, SecFormatBuf *formatBuf) { int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; int textLen; if (formatBuf->str == NULL) { /* NULL passed, use special string */ formatBuf->str = g_strNullString; } if (finalPrecision == SECUREC_INT_MAX) { /* precision NOT assigned */ /* The strlen performance is high when the string length is greater than 32 */ textLen = (int)strlen(formatBuf->str); } else { /* precision assigned */ size_t tmpLen; SECUREC_CALC_STR_LEN(formatBuf->str, (size_t)(unsigned int)finalPrecision, &tmpLen); textLen = (int)tmpLen; } return textLen; } #if SECUREC_HAVE_WCHART static int SecDecodeTypeSwchar(SecFormatAttr *attr, SecFormatBuf *formatBuf) { int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; int textLen; attr->bufferIsWide = 1; if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ formatBuf->wStr = g_wStrNullString; } /* textLen in wchar_t */ SECUREC_CALC_WSTR_LEN(formatBuf->wStr, finalPrecision, &textLen); return textLen; } #endif /* * Decoded string identifier */ static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf) { int textLen; #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX)) attr->flags &= ~SECUREC_FLAG_LEADZERO; #endif formatBuf->str = argPtr; #ifdef SECUREC_FOR_WCHAR #if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) if (!(attr->flags & SECUREC_FLAG_LONG)) { attr->flags |= SECUREC_FLAG_SHORT; } #endif if (attr->flags & SECUREC_FLAG_SHORT) { /* textLen now contains length in multibyte chars */ textLen = SecDecodeTypeSchar(attr, formatBuf); } else { /* textLen now contains length in wide chars */ textLen = SecDecodeTypeSwchar(attr, formatBuf); } #else /* SECUREC_FOR_WCHAR */ if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { /* textLen now contains length in wide chars */ #if SECUREC_HAVE_WCHART textLen = SecDecodeTypeSwchar(attr, formatBuf); #else textLen = 0; #endif } else { /* textLen now contains length in multibyte chars */ textLen = SecDecodeTypeSchar(attr, formatBuf); } #endif /* SECUREC_FOR_WCHAR */ return textLen; } /* * Write one character to dest buffer */ static void SecOutputOneChar(SecChar ch, SecPrintfStream *stream, int *counter) { /* normal state, write character */ if (SECUREC_IS_REST_BUF_ENOUGH(stream, 1)) { /* only one char */ SECUREC_SAFE_WRITE_CHAR(ch, stream, counter); /* char * cast to wchar * */ } else { #ifdef SECUREC_FOR_WCHAR SecWriteCharW(ch, stream, counter); #else /* optimize function call to code */ *counter = -1; stream->count = -1; #endif } } /* * Check precison in format */ static int SecDecodePrecision(SecChar ch, SecFormatAttr *formatAttr) { if (formatAttr->dynPrecision == 0) { /* add digit to current precision */ if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->precision)) { return -1; } formatAttr->precision = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->precision) + (unsigned char)(ch - SECUREC_CHAR('0')); } else { if (formatAttr->precision < 0) { formatAttr->precision = -1; } if (formatAttr->precision > SECUREC_MAX_WIDTH_LEN) { return -1; } } return 0; } /* * Check width in format */ static int SecDecodeWidth(SecChar ch, SecFormatAttr *formatAttr, SecFmtState lastState) { if (formatAttr->dynWidth == 0) { if (lastState != STAT_WIDTH) { formatAttr->fldWidth = 0; } if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->fldWidth)) { return -1; } formatAttr->fldWidth = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->fldWidth) + (unsigned char)(ch - SECUREC_CHAR('0')); } else { if (formatAttr->fldWidth < 0) { formatAttr->flags |= SECUREC_FLAG_LEFT; formatAttr->fldWidth = (-formatAttr->fldWidth); if (formatAttr->fldWidth > SECUREC_MAX_WIDTH_LEN) { return -1; } } } return 0; } #ifdef SECUREC_FOR_WCHAR /* * Formatting output core functions for wchar version.Called by a function such as vswprintf_s * argList must not be declare as const */ static int SecOutputSW(SecPrintfStream *stream, const wchar_t *cFormat, va_list argList) #else /* * Formatting output core functions for char version.Called by a function such as vsnprintf_s */ static int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argList) #endif { const SecChar *format = cFormat; #if SECUREC_ENABLE_SPRINTF_FLOAT char *floatBuf = NULL; #endif SecFormatBuf formatBuf; static const char *itoaUpperDigits = "0123456789ABCDEFX"; static const char *itoaLowerDigits = "0123456789abcdefx"; const char *digits = itoaUpperDigits; unsigned int radix = SECUREC_RADIX_DECIMAL; int charsOut; /* characters written */ int prefixLen = 0; /* Must be initialized or compiler alerts */ int padding = 0; int textLen; /* length of the text */ int noOutput = 0; /* Must be initialized or compiler alerts */ SecFmtState state; SecFmtState lastState; SecChar prefix[SECUREC_PREFIX_LEN] = { 0 }; SecChar ch; /* currently read character */ static const unsigned char stateTable[SECUREC_STATE_TABLE_SIZE] = { /* type 0: nospecial meanin; * 1: '%'; * 2: '.' * 3: '*' * 4: '0' * 5: '1' ... '9' * 6: ' ', '+', '-', '#' * 7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j' * 8: 'd','o','u','i','x','X','e','f','g' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, /* fill zero for normal char 128 byte for 0x80 - 0xff */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* state 0: normal * 1: percent * 2: flag * 3: width * 4: dot * 5: precis * 6: size * 7: type * 8: invalid */ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00 }; SecFormatAttr formatAttr; SecBuffer buffer; formatAttr.flags = 0; formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */ formatAttr.fldWidth = 0; formatAttr.precision = 0; formatAttr.dynWidth = 0; formatAttr.dynPrecision = 0; charsOut = 0; textLen = 0; state = STAT_NORMAL; /* starting state */ formatBuf.str = NULL; /* loop each format character */ /* remove format != NULL */ while ((ch = *format) != SECUREC_CHAR('\0') && charsOut >= 0) { ++format; lastState = state; state = SECUREC_DECODE_STATE(ch, stateTable, lastState); switch (state) { case STAT_NORMAL: SecOutputOneChar(ch, stream, &charsOut); continue; case STAT_PERCENT: /* set default values */ prefixLen = 0; noOutput = 0; formatAttr.flags = 0; formatAttr.fldWidth = 0; formatAttr.precision = -1; formatAttr.bufferIsWide = 0; formatAttr.dynWidth = 0; formatAttr.dynPrecision = 0; break; case STAT_FLAG: /* set flag based on which flag character */ SecDecodeFlags(ch, &formatAttr); break; case STAT_WIDTH: /* update width value */ if (ch == SECUREC_CHAR('*')) { /* get width */ formatAttr.fldWidth = (int)va_arg(argList, int); formatAttr.dynWidth = 1; } else { formatAttr.dynWidth = 0; } if (SecDecodeWidth(ch, &formatAttr, lastState) != 0) { return -1; } break; case STAT_DOT: formatAttr.precision = 0; break; case STAT_PRECIS: /* update precison value */ if (ch == SECUREC_CHAR('*')) { /* get precision from arg list */ formatAttr.precision = (int)va_arg(argList, int); formatAttr.dynPrecision = 1; } else { formatAttr.dynPrecision = 0; } if (SecDecodePrecision(ch, &formatAttr) != 0) { return -1; } break; case STAT_SIZE: /* read a size specifier, set the formatAttr.flags based on it */ if (SecDecodeSize(ch, &formatAttr, &format) != 0) { /* Compatibility code for "%I" just print I */ SecOutputOneChar(ch, stream, &charsOut); state = STAT_NORMAL; continue; } break; case STAT_TYPE: switch (ch) { case SECUREC_CHAR('C'): /* wide char */ if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { #ifdef SECUREC_FOR_WCHAR formatAttr.flags |= SECUREC_FLAG_SHORT; #else formatAttr.flags |= SECUREC_FLAG_WIDECHAR; #endif } /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('c'): do { unsigned int cValue = (unsigned int)va_arg(argList, int); textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer); if (textLen < 0) { noOutput = 1; } } SECUREC_WHILE_ZERO; break; case SECUREC_CHAR('S'): /* wide char string */ if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { #ifndef SECUREC_FOR_WCHAR formatAttr.flags |= SECUREC_FLAG_WIDECHAR; #else formatAttr.flags |= SECUREC_FLAG_SHORT; #endif } /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('s'): do { char *argPtr = (char *)va_arg(argList, char *); textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf); } SECUREC_WHILE_ZERO; break; case SECUREC_CHAR('n'): /* higher risk disable it */ return -1; case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */ /* convert format char to lower , use Explicit conversion to clean up compilation warning */ ch = (SecChar)(ch + ((SecChar)(SECUREC_CHAR('a')) - (SECUREC_CHAR('A')))); /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('a'): #if SECUREC_ENABLE_SPRINTF_FLOAT do { int bufferSize = 0; /* size of formatBuf.str */ /* floating point conversion */ formatBuf.str = buffer.str; /* output buffer for float string with default size */ /* compute the precision value */ if (formatAttr.precision < 0) { formatAttr.precision = SECUREC_FLOAT_DEFAULT_PRECISION; } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) { formatAttr.precision = 1; } /* calc buffer size to store double value * The maximum length of SECUREC_MAX_WIDTH_LEN is enough */ if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE_LB)) { noOutput = 1; break; } /* Long double needs to meet the basic print length */ bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision + SECUREC_FLOAT_BUF_EXT; } else { if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE)) { noOutput = 1; break; } /* Double needs to meet the basic print length */ bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision + SECUREC_FLOAT_BUF_EXT; } if (formatAttr.fldWidth > bufferSize) { bufferSize = formatAttr.fldWidth + SECUREC_FLOAT_BUF_EXT; } if (bufferSize > SECUREC_BUFFER_SIZE) { /* the current vlaue of SECUREC_BUFFER_SIZE could NOT store the * formatted float string */ floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize)); if (floatBuf != NULL) { formatBuf.str = floatBuf; } else { noOutput = 1; break; } } do { /* add following code to call system sprintf API for float number */ const SecChar *pFloatFmt = format - 2; /* sub 2 to the position before 'f' or 'g' */ int k; int fFmtStrLen; char fFmtBuf[SECUREC_FMT_STR_LEN]; char *fFmtStr = fFmtBuf; char *fFmtHeap = NULL; /* to clear warning */ while (SECUREC_CHAR('%') != *pFloatFmt) { /* must meet '%' */ --pFloatFmt; } fFmtStrLen = (int)((format - pFloatFmt) + 1); /* with ending terminator */ if (fFmtStrLen > SECUREC_FMT_STR_LEN) { /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */ fFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fFmtStrLen)); if (fFmtHeap == NULL) { noOutput = 1; break; } else { for (k = 0; k < fFmtStrLen - 1; ++k) { /* convert wchar to char */ fFmtHeap[k] = (char)(pFloatFmt[k]); /* copy the format string */ } fFmtHeap[k] = '\0'; fFmtStr = fFmtHeap; } } else { /* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */ for (k = 0; k < fFmtStrLen - 1; ++k) { /* convert wchar to char */ fFmtBuf[k] = (char)(pFloatFmt[k]); /* copy the format string */ } fFmtBuf[k] = '\0'; } if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT long double tmp = (long double)va_arg(argList, long double); textLen = SecFormatLongDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); #else double tmp = (double)va_arg(argList, double); textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); #endif } else { double tmp = (double)va_arg(argList, double); textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); } if (fFmtHeap != NULL) { /* if buffer is alloced on heap, free it */ SECUREC_FREE(fFmtHeap); fFmtHeap = NULL; /* to clear e438 last value assigned not used , the compiler will * optimize this code */ (void)fFmtHeap; } if (textLen < 0 || textLen >= bufferSize) { /* bufferSize is large enough, just validation the return value */ noOutput = 1; break; } /* no padding ,this variable to calculate amount of padding */ formatAttr.fldWidth = textLen; prefixLen = 0; /* no padding ,this variable to calculate amount of padding */ formatAttr.flags = 0; /* clear all internal formatAttr.flags */ break; } SECUREC_WHILE_ZERO; } SECUREC_WHILE_ZERO; break; #else return -1; #endif case SECUREC_CHAR('p'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('x'): /* unsigned lower hex output */ digits = itoaLowerDigits; radix = SECUREC_RADIX_HEX; switch (ch) { case SECUREC_CHAR('p'): /* print a pointer */ #if defined(SECUREC_COMPATIBLE_WIN_FORMAT) formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; #else formatAttr.flags |= SECUREC_FLAG_POINTER; #endif #ifdef SECUREC_ON_64BITS formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */ #else formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */ #endif #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) #if defined(SECUREC_VXWORKS_PLATFORM) formatAttr.precision = 1; #else formatAttr.precision = 0; #endif formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ break; #else /* not linux vxwoks */ #if defined(_AIX) || defined(SECUREC_ON_SOLARIS) formatAttr.precision = 1; #else formatAttr.precision = 2 * sizeof(void *); /* 2 precision of different systems */ #endif #endif #if defined(SECUREC_ON_UNIX) break; #endif /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ /* unsigned upper hex output */ digits = itoaUpperDigits; break; default: break; } if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { /* alternate form means '0x' prefix */ prefix[0] = SECUREC_CHAR('0'); prefix[1] = (SecChar)(digits[16]); /* 16 for 'x' or 'X' */ #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) if (ch == 'p') { prefix[1] = SECUREC_CHAR('x'); } #endif #if defined(_AIX) || defined(SECUREC_ON_SOLARIS) if (ch == 'p') { prefixLen = 0; } else { prefixLen = SECUREC_PREFIX_LEN; } #else prefixLen = SECUREC_PREFIX_LEN; #endif } /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('u'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('o'): /* fall-through */ /* FALLTHRU */ switch (ch) { case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ /* signed decimal output */ formatAttr.flags |= SECUREC_FLAG_SIGNED; /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('u'): radix = SECUREC_RADIX_DECIMAL; break; case SECUREC_CHAR('o'): /* unsigned octal output */ radix = SECUREC_RADIX_OCTAL; if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { /* alternate form means force a leading 0 */ formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL; } break; default: break; } do { SecUnsignedInt64 number = 0; /* number to convert */ SecInt64 l; /* temp long value */ /* read argument into variable l */ if (formatAttr.flags & SECUREC_FLAG_I64) { l = (SecInt64)va_arg(argList, SecInt64); } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) { l = (SecInt64)va_arg(argList, SecInt64); } else #ifdef SECUREC_ON_64BITS if (formatAttr.flags & SECUREC_FLAG_LONG) { l = (long)va_arg(argList, long); } else #endif /* SECUREC_ON_64BITS */ if (formatAttr.flags & SECUREC_FLAG_CHAR) { if (formatAttr.flags & SECUREC_FLAG_SIGNED) { l = (char)va_arg(argList, int); /* sign extend */ if (l >= 128) { /* 128 on some platform, char is always unsigned */ SecUnsignedInt64 tmpL = (SecUnsignedInt64)l; unsigned char tmpCh = (unsigned char)(~(tmpL)); l = tmpCh + 1; formatAttr.flags |= SECUREC_FLAG_NEGATIVE; } } else { l = (unsigned char)va_arg(argList, int); /* zero-extend */ } } else if (formatAttr.flags & SECUREC_FLAG_SHORT) { if (formatAttr.flags & SECUREC_FLAG_SIGNED) { l = (short)va_arg(argList, int); /* sign extend */ } else { l = (unsigned short)va_arg(argList, int); /* zero-extend */ } } #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) { l = (ptrdiff_t)va_arg(argList, ptrdiff_t); /* sign extend */ } else if (formatAttr.flags & SECUREC_FLAG_SIZE) { if (formatAttr.flags & SECUREC_FLAG_SIGNED) { /* No suitable macros were found to handle the branch */ if (SecIsSameSize(sizeof(size_t), sizeof(long))) { l = va_arg(argList, long); /* sign extend */ } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) { l = va_arg(argList, long long); /* sign extend */ } else { l = va_arg(argList, int); /* sign extend */ } } else { l = (SecInt64)(size_t)va_arg(argList, size_t); /* sign extend */ } } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) { if (formatAttr.flags & SECUREC_FLAG_SIGNED) { l = va_arg(argList, SecInt64); /* sign extend */ } else { /* sign extend */ l = (SecInt64)(SecUnsignedInt64)va_arg(argList, SecUnsignedInt64); } } #endif else { if (formatAttr.flags & SECUREC_FLAG_SIGNED) { l = va_arg(argList, int); /* sign extend */ } else { l = (unsigned int)va_arg(argList, int); /* zero-extend */ } } /* check for negative; copy into number */ if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) { number = (SecUnsignedInt64)(-l); formatAttr.flags |= SECUREC_FLAG_NEGATIVE; } else { number = (SecUnsignedInt64)l; } if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) && #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) && #endif #ifdef SECUREC_ON_64BITS ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) && ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) && #if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) && #endif #endif ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) { number &= 0xffffffff; /* use 0xffffffff as 32 bit mask */ } /* check precision value for default */ if (formatAttr.precision < 0) { formatAttr.precision = 1; /* default precision */ } else { #if defined(SECUREC_COMPATIBLE_WIN_FORMAT) formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; #else if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) { formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; } #endif if (formatAttr.precision > SECUREC_MAX_PRECISION) { formatAttr.precision = SECUREC_MAX_PRECISION; } } /* Check if data is 0; if so, turn off hex prefix, * 'p' add 0x prefix, otherwise not add prefix */ if (number == 0) { #if !(defined(SECUREC_VXWORKS_PLATFORM) || defined(__hpux)) prefixLen = 0; #else if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE)) { prefixLen = SECUREC_PREFIX_LEN; } else { prefixLen = 0; } #endif } /* Convert data to ASCII */ formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE]; if (number > 0) { #ifdef SECUREC_ON_64BITS switch (radix) { /* the compiler will optimize each one */ case SECUREC_RADIX_DECIMAL: SECUREC_SPECIAL_QWORD_BASE10(number); break; case SECUREC_RADIX_HEX: SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX); break; case SECUREC_RADIX_OCTAL: SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL); break; default: break; } #else /* for 32 bits system */ if (number <= 0xFFFFFFFFUL) { /* in most case, the value to be converted is small value */ SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; switch (radix) { case SECUREC_RADIX_HEX: SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_HEX); break; case SECUREC_RADIX_OCTAL: SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_OCTAL); break; #ifdef _AIX /* the compiler will optimize div 10 */ case SECUREC_RADIX_DECIMAL: SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_DECIMAL); break; #else case SECUREC_RADIX_DECIMAL: do { /* fast div 10 */ SecUnsignedInt32 q; SecUnsignedInt32 r; do { *--formatBuf.str = digits[n32Tmp % SECUREC_RADIX_DECIMAL]; q = (n32Tmp >> 1) + (n32Tmp >> 2); /* fast div magic 2 */ q = q + (q >> 4); /* fast div magic 4 */ q = q + (q >> 8); /* fast div magic 8 */ q = q + (q >> 16); /* fast div magic 16 */ q = q >> 3; /* fast div magic 3 */ r = n32Tmp - SECUREC_MUL_TEN(q); n32Tmp = (r > 9) ? (q + 1) : q; /* fast div magic 9 */ } while (n32Tmp != 0); } SECUREC_WHILE_ZERO; break; #endif default: break; } /* end switch */ } else { /* the value to be converted is greater than 4G */ #if defined(SECUREC_VXWORKS_VERSION_5_4) do { SecUnsignedInt32 digit = 0; /* ascii value of digit */ SecUnsignedInt64 quotient = 0; if (SecU64Div32(number,(SecUnsignedInt32)radix, "ient, &digit) != 0) { noOutput = 1; break; } *--formatBuf.str = digits[digit]; number = quotient; } while (number != 0); #else switch (radix) { /* the compiler will optimize div 10 */ case SECUREC_RADIX_DECIMAL: SECUREC_SPECIAL_QWORD_BASE10(number); break; case SECUREC_RADIX_OCTAL: SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL); break; case SECUREC_RADIX_HEX: SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX); break; default: break; } #endif } #endif } /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */ textLen = (int)(size_t)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str); if (formatAttr.precision > textLen) { int ii; for (ii = 0; ii < formatAttr.precision - textLen; ++ii) { *--formatBuf.str = '0'; } textLen = formatAttr.precision; } /* Force a leading zero if FORCEOCTAL flag set */ if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && (textLen == 0 || formatBuf.str[0] != '0')) { *--formatBuf.str = '0'; ++textLen; /* add a zero */ } } SECUREC_WHILE_ZERO; break; default: break; } while (noOutput < 1) { if (formatAttr.flags & SECUREC_FLAG_SIGNED) { if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) { /* prefix is a '-' */ prefix[0] = SECUREC_CHAR('-'); prefixLen = 1; } else if (formatAttr.flags & SECUREC_FLAG_SIGN) { /* prefix is '+' */ prefix[0] = SECUREC_CHAR('+'); prefixLen = 1; } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) { /* prefix is ' ' */ prefix[0] = SECUREC_CHAR(' '); prefixLen = 1; } } #if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX)) if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (textLen == 0)) { formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1]; *formatBuf.str-- = '\0'; *formatBuf.str-- = ')'; *formatBuf.str-- = 'l'; *formatBuf.str-- = 'i'; *formatBuf.str-- = 'n'; *formatBuf.str = '('; textLen = 5; /* length of (nil) is 5 */ } #endif /* calculate amount of padding */ padding = (formatAttr.fldWidth - textLen) - prefixLen; /* put out the padding, prefix, and text, in the correct order */ if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) { /* pad on left with blanks */ if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { /* char * cast to wchar * */ SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); } else { SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); } } /* write prefix */ if (prefixLen > 0) { SecChar *pPrefix = prefix; if (SECUREC_IS_REST_BUF_ENOUGH(stream, prefixLen)) { /* max prefix len is 2, use loop copy */ /* char * cast to wchar * in WCHAR version */ SECUREC_SAFE_WRITE_STR_OPT(pPrefix, prefixLen, stream, &charsOut); } else { SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut); } } if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) { /* write leading zeros */ if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { /* char * cast to wchar * */ SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut); } else { SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut); } } /* write text */ #ifndef SECUREC_FOR_WCHAR if (formatAttr.bufferIsWide != 0 && (textLen > 0)) { #if SECUREC_HAVE_WCTOMB wchar_t *p = formatBuf.wStr; int count = textLen; while (count > 0) { char tmpBuf[SECUREC_MB_LEN + 1]; SECUREC_MASK_MSVC_CRT_WARNING int retVal = wctomb(tmpBuf, *p); SECUREC_END_MASK_MSVC_CRT_WARNING if (retVal <= 0) { charsOut = -1; break; } SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut); --count; ++p; } #else charsOut = -1; break; #endif } else { if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) { SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut); } else { SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut); } } #else /* SECUREC_FOR_WCHAR */ if (formatAttr.bufferIsWide == 0 && textLen > 0) { #if SECUREC_HAVE_MBTOWC int count = textLen; char *p = formatBuf.str; while (count > 0) { wchar_t wChar = L'\0'; int retVal = mbtowc(&wChar, p, (size_t)MB_CUR_MAX); if (retVal <= 0) { charsOut = -1; break; } SecWriteCharW(wChar, stream, &charsOut); p += retVal; count -= retVal; } #else charsOut = -1; break; #endif } else { if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) { /* char * cast to wchar * */ SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); } else { SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut); } } #endif /* SECUREC_FOR_WCHAR */ if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) { /* pad on right with blanks */ if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { /* char * cast to wchar * */ SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); } else { SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); } } break; } #if SECUREC_ENABLE_SPRINTF_FLOAT if (floatBuf != NULL) { SECUREC_FREE(floatBuf); floatBuf = NULL; } #endif break; case STAT_INVALID: return -1; default: return -1; /* input format is wrong, directly return */ } } if (state != STAT_NORMAL && state != STAT_TYPE) { return -1; } return charsOut; /* the number of characters written */ } #endif /* OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */