|
- /**
- * 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 */
|