• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright 2020 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
18#define OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
19
20#define SECUREC_NULL_STRING_SIZE            8
21#define SECUREC_STATE_TABLE_SIZE              337
22#define SECUREC_OFFSET_BITS_WORD            16
23#define SECUREC_OFFSET_BITS_DWORD           32
24
25#define SECUREC_OFFSET_DIV_OCTAL            3
26#define SECUREC_OFFSET_DIV_HEX              4
27#define SECUREC_RADIX_OCTAL                 8
28#define SECUREC_RADIX_DECIMAL               10
29#define SECUREC_RADIX_HEX                   16
30/* Use two displacements to eliminate compilation warnings */
31#define SECUREC_SHR_DWORD(x)                (((x) >> 16) >> 16)
32#define SECUREC_PREFIX_LEN                  2
33/* size include '+' and '\0' */
34#define SECUREC_FLOAT_BUF_EXT               2
35
36
37#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K
38#define SECUREC_FMT_STR_LEN                 8
39#else
40#define SECUREC_FMT_STR_LEN                 16
41#endif
42
43typedef struct {
44    unsigned int flags;
45    int fldWidth;
46    int precision;
47    int bufferIsWide;           /* flag for buffer contains wide chars ;0 is not wide char */
48    int dynWidth;               /* %*   1 width from variable parameter ;0 not */
49    int dynPrecision;           /* %.*  1 precision from variable parameter ;0 not */
50} SecFormatAttr;
51
52typedef union {
53    char *str;                  /* not a null terminated  string */
54#if SECUREC_HAVE_WCHART
55    wchar_t *wStr;
56#endif
57} SecFormatBuf;
58
59typedef union {
60    char str[SECUREC_BUFFER_SIZE + 1];
61#ifdef SECUREC_FOR_WCHAR
62    wchar_t wStr[SECUREC_BUFFER_SIZE + 1];
63#endif
64} SecBuffer;
65
66#if SECUREC_ENABLE_SPRINTF_FLOAT
67/* call system sprintf to format float value */
68static int SecIndirectSprintf(char *strDest, const char *format, ...)
69{
70    int ret;                    /* If initialization causes  e838 */
71    va_list argList;
72
73    va_start(argList, format);
74    SECUREC_MASK_MSVC_CRT_WARNING
75    ret = vsprintf(strDest, format, argList);
76    SECUREC_END_MASK_MSVC_CRT_WARNING
77    va_end(argList);
78    (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */
79
80    return ret;
81}
82
83#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
84/* out put long double value to dest */
85static int SecFormatLongDboule(char *strDest,const SecFormatAttr *formatAttr, const char *fmt, long double ldValue)
86{
87    int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth);
88    if (formatAttr->dynWidth && formatAttr->dynPrecision) {
89        return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, ldValue);
90    } else if (formatAttr->dynWidth) {
91        return SecIndirectSprintf(strDest, fmt, fldWidth, ldValue);
92    } else if (formatAttr->dynPrecision) {
93        return SecIndirectSprintf(strDest, fmt, formatAttr->precision, ldValue);
94    }
95    return SecIndirectSprintf(strDest, fmt, ldValue);
96}
97#endif
98
99/* out put double value to dest */
100static int SecFormatDboule(char *strDest, const SecFormatAttr *formatAttr, const char *fmt, double dValue)
101{
102    int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth);
103    if (formatAttr->dynWidth && formatAttr->dynPrecision) {
104        return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, dValue);
105    } else if (formatAttr->dynWidth) {
106        return SecIndirectSprintf(strDest, fmt, fldWidth, dValue);
107    } else if (formatAttr->dynPrecision) {
108        return SecIndirectSprintf(strDest, fmt, formatAttr->precision, dValue);
109    }
110    return SecIndirectSprintf(strDest, fmt, dValue);
111}
112#endif
113
114#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
115/* to clear e506 warning */
116static int SecIsSameSize(size_t sizeA, size_t sizeB)
117{
118    return sizeA == sizeB;
119}
120#endif
121
122#define SECUREC_SPECIAL_DWORD(val32, numBase) do { \
123    --formatBuf.str; \
124    *(formatBuf.str) = digits[(val32) % (numBase)]; \
125} while (((val32) /= (numBase)) != 0)
126
127#if defined(SECUREC_USE_SPECIAL_DIV64) || (defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS))
128/*
129 * Fast divide by 10 algorithm.
130 * Calculation divisor multiply  0xcccccccccccccccdULL, resultHi64 >> 3 as quotient
131 */
132static void SecU64Div10(SecUnsignedInt64 divisor, SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder)
133{
134    SecUnsignedInt64 mask = 0xffffffffULL; /* use 0xffffffffULL as 32 bit mask */
135    SecUnsignedInt64 magicHi = 0xccccccccULL; /* fast divide 10 magic numbers high 32bit 0xccccccccULL */
136    SecUnsignedInt64 magicLow = 0xcccccccdULL; /* fast divide 10 magic numbers low 32bit  0xcccccccdULL */
137    SecUnsignedInt64 divisorHi = (SecUnsignedInt64)(SECUREC_SHR_DWORD(divisor)); /* hig 32 bit use  */
138    SecUnsignedInt64 divisorLow = (SecUnsignedInt64)(divisor & mask); /* low 32 bit mask */
139    SecUnsignedInt64 factorHi = divisorHi * magicHi;
140    SecUnsignedInt64 factorLow1 = divisorHi * magicLow;
141    SecUnsignedInt64 factorLow2 = divisorLow * magicHi;
142    SecUnsignedInt64 factorLow3 = divisorLow * magicLow;
143    SecUnsignedInt64 carry = (factorLow1 & mask) + (factorLow2 & mask) + SECUREC_SHR_DWORD(factorLow3);
144    SecUnsignedInt64 resultHi64 = factorHi + SECUREC_SHR_DWORD(factorLow1) + \
145                                   SECUREC_SHR_DWORD(factorLow2) + SECUREC_SHR_DWORD(carry);
146
147    *quotient = resultHi64 >> 3; /* fast divide 10 magic numbers 3 */
148    *remainder = (SecUnsignedInt32)(divisor - ((*quotient) * 10)); /* quotient mul 10 */
149    return;
150}
151#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)
152/*
153 * Divide function for VXWORKS
154 */
155static int SecU64Div32(SecUnsignedInt64 divisor, SecUnsignedInt32 radix,
156    SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder)
157{
158    switch (radix) {
159        case SECUREC_RADIX_DECIMAL:
160            SecU64Div10(divisor, quotient, remainder);
161            break;
162        case SECUREC_RADIX_HEX:
163            *quotient = divisor >> SECUREC_OFFSET_DIV_HEX;
164            *remainder = divisor & 0xfULL; /* mask one hex number by 0xfULL */
165            break;
166        case SECUREC_RADIX_OCTAL:
167            *quotient = divisor >> SECUREC_OFFSET_DIV_OCTAL;
168            *remainder = divisor & 0x7ULL; /* mask one hex number by 0x7ULL */
169            break;
170        default:
171            return -1;
172    }
173    return 0;
174}
175#endif
176#endif
177
178#if defined(SECUREC_USE_SPECIAL_DIV64)
179/* The compiler does not provide 64 bit division problems */
180#define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \
181    SecUnsignedInt64 quotient = 0; \
182    SecUnsignedInt32 digit = 0; \
183    SecU64Div10((val64), &(quotient), &(digit)); \
184    --formatBuf.str; \
185    *(formatBuf.str) = digits[digit]; \
186    (val64) = quotient; \
187} while ((val64) != 0)
188#else
189#define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \
190    --formatBuf.str; \
191    *(formatBuf.str) = digits[(val64) % SECUREC_RADIX_DECIMAL]; \
192} while (((val64) /= SECUREC_RADIX_DECIMAL) != 0)
193#endif
194#define SECUREC_SPECIAL_QWORD(val64, numBase) do { \
195    --formatBuf.str; \
196    *(formatBuf.str) = digits[(val64) % (numBase)]; \
197} while (((val64) /= (numBase)) != 0)
198
199
200#define SECUREC_SAFE_WRITE_STR_OPT(src, txtLen, outStream, outChars) do { \
201    int ii_; \
202    for (ii_ = 0; ii_ < (txtLen); ++ii_) { \
203        *((SecChar *)(void *)((outStream)->cur)) = *(SecChar *)(src); \
204        (outStream)->cur += sizeof(SecChar); \
205        (src) = (src) + 1; \
206    } \
207    (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \
208    *(outChars) = *(outChars) + (txtLen); \
209} SECUREC_WHILE_ZERO
210
211#define SECUREC_SAFE_WRITE_STR(src, txtLen, outStream, outChars) do { \
212    if ((txtLen) < 12) { /* performance optimization for mobile number length 12 */ \
213        SECUREC_SAFE_WRITE_STR_OPT((src), (txtLen), (outStream), (outChars)); \
214    } else { \
215        SecDoMemcpy((outStream)->cur, (src), ((size_t)(unsigned int)(txtLen) * (sizeof(SecChar)))); \
216        (outStream)->cur += (size_t)((size_t)(unsigned int)(txtLen) * (sizeof(SecChar))); \
217        (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \
218        *(outChars) = *(outChars) + (txtLen); \
219    } \
220} SECUREC_WHILE_ZERO
221
222#define SECUREC_SAFE_WRITE_CHAR(c, outStream, outChars) do { \
223    *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(c); \
224    (outStream)->cur += sizeof(SecChar); \
225    (outStream)->count -= (int)(sizeof(SecChar)); \
226    *(outChars) = *(outChars) + 1; \
227} SECUREC_WHILE_ZERO
228
229#define SECUREC_SAFE_PADDING(padChar, padLen, outStream, outChars) do { \
230    int ii_; \
231    for (ii_ = 0; ii_ < (padLen); ++ii_) { \
232        *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(padChar); \
233        (outStream)->cur += sizeof(SecChar); \
234    } \
235    (outStream)->count -= (padLen) * (int)(sizeof(SecChar)); \
236    *(outChars) = *(outChars) + (padLen); \
237} SECUREC_WHILE_ZERO
238
239/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */
240#define SECUREC_IS_REST_BUF_ENOUGH(stream, needLen) ((int)((stream)->count - \
241    (int)(needLen) * (int)(sizeof(SecChar))) >= 0)
242
243#define SECUREC_FMT_STATE_OFFSET  256
244#ifdef SECUREC_FOR_WCHAR
245#define SECUREC_FMT_TYPE(c, fmtTable)  ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \
246    ((fmtTable)[(unsigned char)(c)]) : 0)
247#define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)((((fmtTable)[(SECUREC_FMT_TYPE(c, (fmtTable))) * \
248    ((unsigned char)STAT_INVALID + 1) + \
249    (unsigned char)(lastState) + \
250    SECUREC_FMT_STATE_OFFSET])))
251#else
252#define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)(((fmtTable)[((fmtTable)[(unsigned char)(c)]) * \
253    ((unsigned char)STAT_INVALID + 1) + \
254    (unsigned char)(lastState) + \
255    SECUREC_FMT_STATE_OFFSET]))
256#endif
257
258static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr)
259{
260    switch (ch) {
261        case SECUREC_CHAR(' '):
262            attr->flags |= SECUREC_FLAG_SIGN_SPACE;
263            break;
264        case SECUREC_CHAR('+'):
265            attr->flags |= SECUREC_FLAG_SIGN;
266            break;
267        case SECUREC_CHAR('-'):
268            attr->flags |= SECUREC_FLAG_LEFT;
269            break;
270        case SECUREC_CHAR('0'):
271            attr->flags |= SECUREC_FLAG_LEADZERO;   /* add zero th the front */
272            break;
273        case SECUREC_CHAR('#'):
274            attr->flags |= SECUREC_FLAG_ALTERNATE;  /* output %x with 0x */
275            break;
276        default:
277            break;
278    }
279    return;
280}
281
282
283/*
284 * Decoded size identifier in format string to Reduce the number of lines of function code
285 */
286static int SecDecodeSizeI(SecFormatAttr *attr, const SecChar **format)
287{
288#ifdef SECUREC_ON_64BITS
289    attr->flags |= SECUREC_FLAG_I64;    /* %I  to  INT64 */
290#endif
291    if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) {
292        (*format) += 2; /* add 2 to skip I64 */
293        attr->flags |= SECUREC_FLAG_I64;    /* %I64  to  INT64 */
294    } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) {
295        (*format) += 2; /* add 2 to skip I32 */
296        attr->flags &= ~SECUREC_FLAG_I64;   /* %I64  to  INT32 */
297    } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) ||
298        (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) ||
299        (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) {
300        /* do nothing */
301    } else {
302        /* Compatibility  code for "%I" just print I */
303        return -1;
304    }
305    return 0;
306}
307/*
308 * Decoded size identifier in format string
309 */
310static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format)
311{
312    switch (ch) {
313#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
314        case SECUREC_CHAR('j'):
315            attr->flags |= SECUREC_FLAG_INTMAX;
316            break;
317#endif
318        case SECUREC_CHAR('q'):
319            /* fall-through */ /* FALLTHRU */
320        case SECUREC_CHAR('L'):
321            attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE;
322            break;
323        case SECUREC_CHAR('l'):
324            if (**format == SECUREC_CHAR('l')) {
325                *format = *format + 1;
326                attr->flags |= SECUREC_FLAG_LONGLONG;   /* long long */
327            } else {
328                attr->flags |= SECUREC_FLAG_LONG;   /* long int or wchar_t */
329            }
330            break;
331        case SECUREC_CHAR('t'):
332            attr->flags |= SECUREC_FLAG_PTRDIFF;
333            break;
334#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
335        case SECUREC_CHAR('z'):
336            /* fall-through */ /* FALLTHRU */
337        case SECUREC_CHAR('Z'):
338            attr->flags |= SECUREC_FLAG_SIZE;
339            break;
340#endif
341        case SECUREC_CHAR('I'):
342            if (SecDecodeSizeI(attr, format) != 0) {
343                /* Compatibility  code for "%I" just print I */
344                return -1;
345            }
346            break;
347        case SECUREC_CHAR('h'):
348            if (**format == SECUREC_CHAR('h')) {
349                attr->flags |= SECUREC_FLAG_CHAR;   /* char */
350            } else {
351                attr->flags |= SECUREC_FLAG_SHORT;  /* short int */
352            }
353            break;
354        case SECUREC_CHAR('w'):
355            attr->flags |= SECUREC_FLAG_WIDECHAR;   /* wide char */
356            break;
357        default:
358            break;
359    }
360    return 0;
361}
362
363/*
364 * Decoded char type identifier
365 */
366static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer)
367{
368#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS))
369    attr->flags &= ~SECUREC_FLAG_LEADZERO;
370#endif
371
372#ifdef SECUREC_FOR_WCHAR
373    attr->bufferIsWide = 1;
374    if (attr->flags & SECUREC_FLAG_SHORT) {
375#if SECUREC_HAVE_MBTOWC
376        /* multibyte character to wide  character */
377        char tmpChar[2]; /* One character string, length is 2 */
378        tmpChar[0] = (char)(cValue & 0x00ff);
379        tmpChar[1] = '\0';
380
381        if (mbtowc(buffer->wStr, tmpChar, sizeof(tmpChar)) < 0) {
382            return -1;
383        }
384#else
385        return -1;
386#endif
387    } else {
388        buffer->wStr[0] = (wchar_t)cValue;
389    }
390    formatBuf->wStr = buffer->wStr;
391    return 1;                /* only 1 wide character */
392#else /* SECUREC_FOR_WCHAR */
393    attr->bufferIsWide = 0;
394    if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
395#if SECUREC_HAVE_WCTOMB
396        wchar_t wChar = (wchar_t)cValue;
397        int textLen;
398        /* wide  character  to multibyte character */
399        SECUREC_MASK_MSVC_CRT_WARNING
400        textLen = wctomb(buffer->str, wChar);
401        SECUREC_END_MASK_MSVC_CRT_WARNING
402        if (textLen < 0) {
403            return -1;
404        }
405        formatBuf->str = buffer->str;
406        return textLen;
407#else
408        return -1;
409#endif
410    } else {
411        /* get  multibyte character from argument */
412        unsigned short temp;
413        temp = (unsigned short)cValue;
414        buffer->str[0] = (char)temp;
415        formatBuf->str = buffer->str;
416        return 1; /* only 1 character */
417    }
418#endif
419
420}
421
422/* literal string to print null ptr, define it as array rather than const text area
423 * is to avoid gcc warning with pointing const text with variable
424 */
425#if SECUREC_HAVE_WCHART
426static wchar_t g_wStrNullString[SECUREC_NULL_STRING_SIZE] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' };
427#endif
428static char g_strNullString[SECUREC_NULL_STRING_SIZE] = "(null)";
429
430static int SecDecodeTypeSchar(const SecFormatAttr *attr, SecFormatBuf *formatBuf)
431{
432    int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision;
433    int textLen;
434
435    if (formatBuf->str == NULL) {   /* NULL passed, use special string */
436        formatBuf->str = g_strNullString;
437    }
438    if (finalPrecision == SECUREC_INT_MAX) {
439        /* precision NOT assigned */
440        /* The strlen performance is high when the string length is greater than 32 */
441        textLen = (int)strlen(formatBuf->str);
442    } else {
443        /* precision assigned */
444        size_t tmpLen;
445        SECUREC_CALC_STR_LEN(formatBuf->str, (size_t)(unsigned int)finalPrecision, &tmpLen);
446        textLen = (int)tmpLen;
447    }
448    return textLen;
449}
450
451#if SECUREC_HAVE_WCHART
452static int SecDecodeTypeSwchar(SecFormatAttr *attr, SecFormatBuf *formatBuf)
453{
454    int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision;
455    int textLen;
456
457    attr->bufferIsWide = 1;
458    if (formatBuf->wStr == NULL) {  /* NULL passed, use special string */
459        formatBuf->wStr = g_wStrNullString;
460    }
461    /* textLen in wchar_t */
462    SECUREC_CALC_WSTR_LEN(formatBuf->wStr, finalPrecision, &textLen);
463
464    return textLen;
465}
466#endif
467
468/*
469 * Decoded string identifier
470 */
471static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf)
472{
473    int textLen;
474#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX))
475    attr->flags &= ~SECUREC_FLAG_LEADZERO;
476#endif
477    formatBuf->str = argPtr;
478#ifdef SECUREC_FOR_WCHAR
479#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT)
480    if (!(attr->flags & SECUREC_FLAG_LONG)) {
481        attr->flags |= SECUREC_FLAG_SHORT;
482    }
483#endif
484    if (attr->flags & SECUREC_FLAG_SHORT) {
485        /* textLen now contains length in multibyte chars */
486        textLen = SecDecodeTypeSchar(attr, formatBuf);
487    } else {
488        /* textLen now contains length in wide chars */
489        textLen = SecDecodeTypeSwchar(attr, formatBuf);
490    }
491#else /* SECUREC_FOR_WCHAR */
492    if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
493        /* textLen now contains length in wide chars */
494#if SECUREC_HAVE_WCHART
495        textLen = SecDecodeTypeSwchar(attr, formatBuf);
496#else
497        textLen = 0;
498#endif
499    } else {
500        /* textLen now contains length in multibyte chars */
501        textLen = SecDecodeTypeSchar(attr, formatBuf);
502    }
503#endif /* SECUREC_FOR_WCHAR */
504    return textLen;
505}
506
507/*
508 * Write one character to dest buffer
509 */
510static void SecOutputOneChar(SecChar ch, SecPrintfStream *stream, int *counter)
511{
512    /* normal state, write character */
513    if (SECUREC_IS_REST_BUF_ENOUGH(stream, 1)) { /* only one char */
514        SECUREC_SAFE_WRITE_CHAR(ch, stream, counter); /* char * cast to wchar * */
515    } else {
516#ifdef SECUREC_FOR_WCHAR
517        SecWriteCharW(ch, stream, counter);
518#else
519        /* optimize function call to code */
520        *counter = -1;
521        stream->count = -1;
522#endif
523    }
524}
525
526/*
527 * Check precison in format
528 */
529static int SecDecodePrecision(SecChar ch, SecFormatAttr *formatAttr)
530{
531    if (formatAttr->dynPrecision == 0) {
532        /* add digit to current precision */
533        if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->precision)) {
534            return -1;
535        }
536        formatAttr->precision = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->precision) +
537            (unsigned char)(ch - SECUREC_CHAR('0'));
538    } else {
539        if (formatAttr->precision < 0) {
540            formatAttr->precision = -1;
541        }
542        if (formatAttr->precision > SECUREC_MAX_WIDTH_LEN) {
543            return -1;
544        }
545    }
546    return 0;
547}
548
549
550/*
551 * Check width in format
552 */
553static int SecDecodeWidth(SecChar ch, SecFormatAttr *formatAttr, SecFmtState lastState)
554{
555    if (formatAttr->dynWidth == 0) {
556        if (lastState != STAT_WIDTH) {
557            formatAttr->fldWidth = 0;
558        }
559        if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->fldWidth)) {
560            return -1;
561        }
562        formatAttr->fldWidth = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->fldWidth) +
563            (unsigned char)(ch - SECUREC_CHAR('0'));
564    } else {
565        if (formatAttr->fldWidth < 0) {
566            formatAttr->flags |= SECUREC_FLAG_LEFT;
567            formatAttr->fldWidth = (-formatAttr->fldWidth);
568            if (formatAttr->fldWidth > SECUREC_MAX_WIDTH_LEN) {
569                return -1;
570            }
571        }
572    }
573    return 0;
574}
575#ifdef SECUREC_FOR_WCHAR
576/*
577 * Formatting output core functions for wchar version.Called by a function such as vswprintf_s
578 * argList must not be declare as const
579 */
580static int SecOutputSW(SecPrintfStream *stream, const wchar_t *cFormat, va_list argList)
581#else
582/*
583 * Formatting output core functions for char version.Called by a function such as vsnprintf_s
584 */
585static int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argList)
586#endif
587{
588    const SecChar *format = cFormat;
589#if SECUREC_ENABLE_SPRINTF_FLOAT
590    char *floatBuf = NULL;
591#endif
592    SecFormatBuf formatBuf;
593    static const char *itoaUpperDigits = "0123456789ABCDEFX";
594    static const char *itoaLowerDigits = "0123456789abcdefx";
595    const char *digits = itoaUpperDigits;
596    unsigned int radix = SECUREC_RADIX_DECIMAL;
597    int charsOut;               /* characters written */
598    int prefixLen = 0;  /* Must be initialized or compiler alerts */
599    int padding = 0;
600    int textLen;                /* length of the text */
601    int noOutput = 0; /* Must be initialized or compiler alerts */
602    SecFmtState state;
603    SecFmtState lastState;
604    SecChar prefix[SECUREC_PREFIX_LEN] = { 0 };
605    SecChar ch;                 /* currently read character */
606    static const unsigned char stateTable[SECUREC_STATE_TABLE_SIZE] = {
607        /* type 0:    nospecial meanin;
608         *  1:   '%';
609         *  2:    '.'
610         *  3:    '*'
611         *  4:    '0'
612         *  5:    '1' ... '9'
613         *  6:    ' ', '+', '-', '#'
614         *  7:     'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j'
615         *  8:     'd','o','u','i','x','X','e','f','g'
616         */
617        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619        0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00,
620        0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621        0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
622        0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
623        0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08,
624        0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
625        /* fill zero  for normal char 128 byte for 0x80 - 0xff */
626        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634        /* state  0: normal
635         *  1: percent
636         *  2: flag
637         *  3: width
638         *  4: dot
639         *  5: precis
640         *  6: size
641         *  7: type
642         *  8: invalid
643         */
644        0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
645        0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05,
646        0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03,
647        0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
648        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00,
649        0x00
650    };
651
652    SecFormatAttr formatAttr;
653    SecBuffer buffer;
654    formatAttr.flags = 0;
655    formatAttr.bufferIsWide = 0;    /* flag for buffer contains wide chars */
656    formatAttr.fldWidth = 0;
657    formatAttr.precision = 0;
658    formatAttr.dynWidth = 0;
659    formatAttr.dynPrecision = 0;
660    charsOut = 0;
661    textLen = 0;
662    state = STAT_NORMAL;        /* starting state */
663    formatBuf.str = NULL;
664
665    /* loop each format character */
666    /* remove format != NULL */
667    while ((ch = *format) != SECUREC_CHAR('\0') && charsOut >= 0) {
668        ++format;
669        lastState = state;
670        state = SECUREC_DECODE_STATE(ch, stateTable, lastState);
671        switch (state) {
672            case STAT_NORMAL:
673                SecOutputOneChar(ch, stream, &charsOut);
674                continue;
675            case STAT_PERCENT:
676                /* set default values */
677                prefixLen = 0;
678                noOutput = 0;
679                formatAttr.flags = 0;
680                formatAttr.fldWidth = 0;
681                formatAttr.precision = -1;
682                formatAttr.bufferIsWide = 0;
683                formatAttr.dynWidth = 0;
684                formatAttr.dynPrecision = 0;
685                break;
686            case STAT_FLAG:
687                /* set flag based on which flag character */
688                SecDecodeFlags(ch, &formatAttr);
689                break;
690            case STAT_WIDTH:
691                /* update width value */
692                if (ch == SECUREC_CHAR('*')) {
693                    /* get width */
694                    formatAttr.fldWidth = (int)va_arg(argList, int);
695                    formatAttr.dynWidth = 1;
696                } else {
697                    formatAttr.dynWidth = 0;
698                }
699                if (SecDecodeWidth(ch, &formatAttr, lastState) != 0) {
700                    return -1;
701                }
702                break;
703            case STAT_DOT:
704                formatAttr.precision = 0;
705                break;
706            case STAT_PRECIS:
707                /* update precison value */
708                if (ch == SECUREC_CHAR('*')) {
709                    /* get precision from arg list */
710                    formatAttr.precision = (int)va_arg(argList, int);
711                    formatAttr.dynPrecision = 1;
712                } else {
713                    formatAttr.dynPrecision = 0;
714                }
715                if (SecDecodePrecision(ch, &formatAttr) != 0) {
716                    return -1;
717                }
718                break;
719            case STAT_SIZE:
720                /* read a size specifier, set the formatAttr.flags based on it */
721                if (SecDecodeSize(ch, &formatAttr, &format) != 0) {
722                    /* Compatibility  code for "%I" just print I */
723                    SecOutputOneChar(ch, stream, &charsOut);
724                    state = STAT_NORMAL;
725                    continue;
726                }
727                break;
728            case STAT_TYPE:
729                switch (ch) {
730                    case SECUREC_CHAR('C'):
731                        /* wide char */
732                        if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
733#ifdef SECUREC_FOR_WCHAR
734                            formatAttr.flags |= SECUREC_FLAG_SHORT;
735#else
736                            formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
737#endif
738                        }
739                        /* fall-through */
740                        /* FALLTHRU */
741                    case SECUREC_CHAR('c'):
742                        do {
743                            unsigned int cValue = (unsigned int)va_arg(argList, int);
744                            textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer);
745                            if (textLen < 0) {
746                                noOutput = 1;
747                            }
748                        } SECUREC_WHILE_ZERO;
749                        break;
750                    case SECUREC_CHAR('S'):    /* wide char string */
751                        if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
752#ifndef SECUREC_FOR_WCHAR
753                            formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
754#else
755                            formatAttr.flags |= SECUREC_FLAG_SHORT;
756#endif
757                        }
758                        /* fall-through */
759                        /* FALLTHRU */
760                    case SECUREC_CHAR('s'):
761                        do {
762                            char *argPtr = (char *)va_arg(argList, char *);
763                            textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf);
764                        } SECUREC_WHILE_ZERO;
765                        break;
766                    case SECUREC_CHAR('n'):
767                        /* higher risk disable it */
768                        return -1;
769                    case SECUREC_CHAR('E'):    /* fall-through */ /* FALLTHRU */
770                    case SECUREC_CHAR('F'):    /* fall-through */ /* FALLTHRU */
771                    case SECUREC_CHAR('G'):    /* fall-through */ /* FALLTHRU */
772                    case SECUREC_CHAR('A'):    /* fall-through */ /* FALLTHRU */
773                        /* convert format char to lower , use Explicit conversion to clean up compilation warning */
774                        ch = (SecChar)(ch + ((SecChar)(SECUREC_CHAR('a')) - (SECUREC_CHAR('A'))));
775                        /* fall-through */
776                        /* FALLTHRU */
777                    case SECUREC_CHAR('e'):    /* fall-through */ /* FALLTHRU */
778                    case SECUREC_CHAR('f'):    /* fall-through */ /* FALLTHRU */
779                    case SECUREC_CHAR('g'):    /* fall-through */ /* FALLTHRU */
780                    case SECUREC_CHAR('a'):
781#if SECUREC_ENABLE_SPRINTF_FLOAT
782                        do {
783                            int bufferSize = 0;         /* size of formatBuf.str */
784                            /* floating point conversion */
785                            formatBuf.str = buffer.str; /* output buffer for float string with default size */
786
787                            /* compute the precision value */
788                            if (formatAttr.precision < 0) {
789                                formatAttr.precision = SECUREC_FLOAT_DEFAULT_PRECISION;
790                            } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) {
791                                formatAttr.precision = 1;
792                            }
793
794                            /* calc buffer size to store double value
795                             * The maximum length of SECUREC_MAX_WIDTH_LEN is enough
796                             */
797                            if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
798                                if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE_LB)) {
799                                    noOutput = 1;
800                                    break;
801                                }
802                                /* Long double needs to meet the basic print length */
803                                bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision + SECUREC_FLOAT_BUF_EXT;
804                            } else {
805                                if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE)) {
806                                    noOutput = 1;
807                                    break;
808                                }
809                                /* Double needs to meet the basic print length */
810                                bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision + SECUREC_FLOAT_BUF_EXT;
811                            }
812                            if (formatAttr.fldWidth > bufferSize) {
813                                bufferSize = formatAttr.fldWidth + SECUREC_FLOAT_BUF_EXT;
814                            }
815
816                            if (bufferSize > SECUREC_BUFFER_SIZE) {
817                                /* the current vlaue of SECUREC_BUFFER_SIZE could NOT store the
818                                 * formatted float string
819                                 */
820                                floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize));
821                                if (floatBuf != NULL) {
822                                    formatBuf.str = floatBuf;
823                                } else {
824                                    noOutput = 1;
825                                    break;
826                                }
827                            }
828
829                            do {
830                                /* add following code to call system sprintf API for float number */
831                                const SecChar *pFloatFmt = format - 2;  /* sub 2 to the position before 'f' or 'g' */
832                                int k;
833                                int fFmtStrLen;
834                                char fFmtBuf[SECUREC_FMT_STR_LEN];
835                                char *fFmtStr = fFmtBuf;
836                                char *fFmtHeap = NULL;    /* to clear warning */
837
838                                while (SECUREC_CHAR('%') != *pFloatFmt) { /* must meet '%' */
839                                    --pFloatFmt;
840                                }
841                                fFmtStrLen = (int)((format - pFloatFmt) + 1);   /* with ending terminator */
842                                if (fFmtStrLen > SECUREC_FMT_STR_LEN) {
843                                    /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */
844                                    fFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fFmtStrLen));
845                                    if (fFmtHeap == NULL) {
846                                        noOutput = 1;
847                                        break;
848                                    } else {
849                                        for (k = 0; k < fFmtStrLen - 1; ++k) {
850                                            /* convert wchar to char */
851                                            fFmtHeap[k] = (char)(pFloatFmt[k]); /* copy the format string */
852                                        }
853                                        fFmtHeap[k] = '\0';
854
855                                        fFmtStr = fFmtHeap;
856                                    }
857                                } else {
858                                    /* purpose of the repeat code is to solve the tool alarm  Redundant_Null_Check */
859                                    for (k = 0; k < fFmtStrLen - 1; ++k) {
860                                        /* convert wchar to char */
861                                        fFmtBuf[k] = (char)(pFloatFmt[k]);  /* copy the format string */
862                                    }
863                                    fFmtBuf[k] = '\0';
864                                }
865
866                                if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
867#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
868                                    long double tmp = (long double)va_arg(argList, long double);
869                                    textLen = SecFormatLongDboule(formatBuf.str, &formatAttr, fFmtStr, tmp);
870#else
871                                    double tmp = (double)va_arg(argList, double);
872                                    textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp);
873#endif
874                                } else {
875                                    double tmp = (double)va_arg(argList, double);
876                                    textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp);
877                                }
878
879                                if (fFmtHeap != NULL) {
880                                    /* if buffer is alloced on heap, free it */
881                                    SECUREC_FREE(fFmtHeap);
882                                    fFmtHeap = NULL;
883                                    /* to clear e438 last value assigned not used , the compiler will
884                                     * optimize this code
885                                     */
886                                    (void)fFmtHeap;
887                                }
888                                if (textLen < 0 || textLen >= bufferSize) {
889                                    /* bufferSize is large enough, just validation the return value */
890                                    noOutput = 1;
891                                    break;
892                                }
893
894                                /* no padding ,this variable to calculate amount of padding */
895                                formatAttr.fldWidth = textLen;
896                                prefixLen = 0;  /* no padding ,this variable to  calculate amount of padding */
897                                formatAttr.flags = 0;   /* clear all internal formatAttr.flags */
898                                break;
899                            } SECUREC_WHILE_ZERO;
900                        } SECUREC_WHILE_ZERO;
901                        break;
902#else
903                        return -1;
904#endif
905                    case SECUREC_CHAR('p'): /* fall-through */ /* FALLTHRU */
906                    case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */
907                    case SECUREC_CHAR('x'):
908                        /* unsigned lower hex output */
909                        digits = itoaLowerDigits;
910                        radix = SECUREC_RADIX_HEX;
911                        switch (ch) {
912                            case SECUREC_CHAR('p'):
913                                /* print a pointer */
914#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
915                                formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
916#else
917                                formatAttr.flags |= SECUREC_FLAG_POINTER;
918#endif
919#ifdef SECUREC_ON_64BITS
920                                formatAttr.flags |= SECUREC_FLAG_I64;   /* converting an int64 */
921#else
922                                formatAttr.flags |= SECUREC_FLAG_LONG;  /* converting a long */
923#endif
924
925#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX))
926#if defined(SECUREC_VXWORKS_PLATFORM)
927                                formatAttr.precision = 1;
928#else
929                                formatAttr.precision = 0;
930#endif
931                                formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */
932                                break;
933#else
934                /* not linux vxwoks */
935#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
936                                formatAttr.precision = 1;
937#else
938                                formatAttr.precision = 2 * sizeof(void *);  /* 2 precision of different systems */
939#endif
940#endif
941
942#if defined(SECUREC_ON_UNIX)
943                                break;
944#endif
945                                /* fall-through */ /* FALLTHRU */
946                            case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */
947                                /* unsigned upper hex output */
948                                digits = itoaUpperDigits;
949                                break;
950                            default:
951                                break;
952                        }
953
954                        if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
955                            /* alternate form means '0x' prefix */
956                            prefix[0] = SECUREC_CHAR('0');
957                            prefix[1] = (SecChar)(digits[16]); /* 16 for 'x' or 'X' */
958
959#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM))
960                            if (ch == 'p') {
961                                prefix[1] = SECUREC_CHAR('x');
962                            }
963#endif
964#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
965                            if (ch == 'p') {
966                                prefixLen = 0;
967                            } else {
968                                prefixLen = SECUREC_PREFIX_LEN;
969                            }
970#else
971                            prefixLen = SECUREC_PREFIX_LEN;
972#endif
973
974                        }
975                        /* fall-through */ /* FALLTHRU */
976                    case SECUREC_CHAR('i'):    /* fall-through */ /* FALLTHRU */
977                    case SECUREC_CHAR('d'):    /* fall-through */ /* FALLTHRU */
978                    case SECUREC_CHAR('u'):    /* fall-through */ /* FALLTHRU */
979                    case SECUREC_CHAR('o'):    /* fall-through */ /* FALLTHRU */
980                        switch (ch) {
981                            case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */
982                            case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */
983                                /* signed decimal output */
984                                formatAttr.flags |= SECUREC_FLAG_SIGNED;
985                                /* fall-through */ /* FALLTHRU */
986                            case SECUREC_CHAR('u'):
987                                radix = SECUREC_RADIX_DECIMAL;
988                                break;
989                            case SECUREC_CHAR('o'):
990                                /* unsigned octal output */
991                                radix = SECUREC_RADIX_OCTAL;
992                                if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
993                                    /* alternate form means force a leading 0 */
994                                    formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL;
995                                }
996                                break;
997                            default:
998                                break;
999                        }
1000
1001                        do {
1002
1003                            SecUnsignedInt64 number = 0;    /* number to convert */
1004                            SecInt64 l; /* temp long value */
1005
1006                            /* read argument into variable l */
1007                            if (formatAttr.flags & SECUREC_FLAG_I64) {
1008                                l = (SecInt64)va_arg(argList, SecInt64);
1009                            } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) {
1010                                l = (SecInt64)va_arg(argList, SecInt64);
1011                            } else
1012#ifdef SECUREC_ON_64BITS
1013                            if (formatAttr.flags & SECUREC_FLAG_LONG) {
1014                                l = (long)va_arg(argList, long);
1015                            } else
1016#endif /* SECUREC_ON_64BITS */
1017                            if (formatAttr.flags & SECUREC_FLAG_CHAR) {
1018                                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1019                                    l = (char)va_arg(argList, int); /* sign extend */
1020                                    if (l >= 128) { /* 128 on some platform, char is always unsigned */
1021                                        SecUnsignedInt64 tmpL = (SecUnsignedInt64)l;
1022                                        unsigned char tmpCh = (unsigned char)(~(tmpL));
1023                                        l = tmpCh + 1;
1024                                        formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
1025                                    }
1026                                } else {
1027                                    l = (unsigned char)va_arg(argList, int);    /* zero-extend */
1028                                }
1029
1030                            } else if (formatAttr.flags & SECUREC_FLAG_SHORT) {
1031                                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1032                                    l = (short)va_arg(argList, int);    /* sign extend */
1033                                } else {
1034                                    l = (unsigned short)va_arg(argList, int);   /* zero-extend */
1035                                }
1036
1037                            }
1038#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
1039                            else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) {
1040                                l = (ptrdiff_t)va_arg(argList, ptrdiff_t);  /* sign extend */
1041                            } else if (formatAttr.flags & SECUREC_FLAG_SIZE) {
1042                                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1043                                    /* No suitable macros were found to handle the branch */
1044                                    if (SecIsSameSize(sizeof(size_t), sizeof(long))) {
1045                                        l = va_arg(argList, long);  /* sign extend */
1046                                    } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) {
1047                                        l = va_arg(argList, long long); /* sign extend */
1048                                    } else {
1049                                        l = va_arg(argList, int);   /* sign extend */
1050                                    }
1051                                } else {
1052                                    l = (SecInt64)(size_t)va_arg(argList, size_t);  /* sign extend */
1053                                }
1054                            } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) {
1055                                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1056                                    l = va_arg(argList, SecInt64);  /* sign extend */
1057                                } else {
1058                                    /* sign extend */
1059                                    l = (SecInt64)(SecUnsignedInt64)va_arg(argList, SecUnsignedInt64);
1060                                }
1061                            }
1062#endif
1063                            else {
1064                                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1065                                    l = va_arg(argList, int);   /* sign extend */
1066                                } else {
1067                                    l = (unsigned int)va_arg(argList, int); /* zero-extend */
1068                                }
1069
1070                            }
1071
1072                            /* check for negative; copy into number */
1073                            if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) {
1074                                number = (SecUnsignedInt64)(-l);
1075                                formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
1076                            } else {
1077                                number = (SecUnsignedInt64)l;
1078                            }
1079
1080                            if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) &&
1081#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
1082                                ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) &&
1083#endif
1084#ifdef SECUREC_ON_64BITS
1085                                ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) &&
1086                                ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) &&
1087#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT)  /* on window 64 system sizeof long is 32bit */
1088                                ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) &&
1089#endif
1090#endif
1091                                ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) {
1092
1093                                    number &= 0xffffffff;  /* use 0xffffffff as 32 bit mask */
1094                            }
1095
1096                            /* check precision value for default */
1097                            if (formatAttr.precision < 0) {
1098                                formatAttr.precision = 1;   /* default precision */
1099                            } else {
1100#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1101                                formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1102#else
1103                                if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) {
1104                                    formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1105                                }
1106#endif
1107                                if (formatAttr.precision > SECUREC_MAX_PRECISION) {
1108                                    formatAttr.precision = SECUREC_MAX_PRECISION;
1109                                }
1110                            }
1111
1112                            /* Check if data is 0; if so, turn off hex prefix,
1113                             * 'p' add 0x prefix, otherwise not add prefix
1114                             */
1115                            if (number == 0) {
1116#if !(defined(SECUREC_VXWORKS_PLATFORM) || defined(__hpux))
1117                                prefixLen = 0;
1118#else
1119                                if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE)) {
1120                                    prefixLen = SECUREC_PREFIX_LEN;
1121                                } else {
1122                                    prefixLen = 0;
1123                                }
1124#endif
1125                            }
1126
1127                            /* Convert data to ASCII */
1128                            formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE];
1129
1130                            if (number > 0) {
1131#ifdef SECUREC_ON_64BITS
1132                                switch (radix) {
1133                                    /* the compiler will optimize each one */
1134                                    case SECUREC_RADIX_DECIMAL:
1135                                        SECUREC_SPECIAL_QWORD_BASE10(number);
1136                                        break;
1137                                    case SECUREC_RADIX_HEX:
1138                                        SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX);
1139                                        break;
1140                                    case SECUREC_RADIX_OCTAL:
1141                                        SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL);
1142                                        break;
1143                                    default:
1144                                        break;
1145                                }
1146#else /* for 32 bits system */
1147                                if (number <= 0xFFFFFFFFUL) {
1148                                    /* in most case, the value to be converted is small value */
1149                                    SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number;
1150                                    switch (radix) {
1151                                        case SECUREC_RADIX_HEX:
1152                                            SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_HEX);
1153                                            break;
1154                                        case SECUREC_RADIX_OCTAL:
1155                                            SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_OCTAL);
1156                                            break;
1157
1158#ifdef _AIX
1159                                        /* the compiler will optimize div 10 */
1160                                        case SECUREC_RADIX_DECIMAL:
1161                                            SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_DECIMAL);
1162                                            break;
1163#else
1164                                        case SECUREC_RADIX_DECIMAL:
1165                                            do {
1166                                                /* fast div 10 */
1167                                                SecUnsignedInt32 q;
1168                                                SecUnsignedInt32 r;
1169                                                do {
1170                                                    *--formatBuf.str = digits[n32Tmp % SECUREC_RADIX_DECIMAL];
1171                                                    q = (n32Tmp >> 1) + (n32Tmp >> 2); /* fast div  magic 2 */
1172                                                    q = q + (q >> 4); /* fast div  magic 4 */
1173                                                    q = q + (q >> 8); /* fast div  magic 8 */
1174                                                    q = q + (q >> 16); /* fast div  magic 16 */
1175                                                    q = q >> 3; /* fast div  magic 3 */
1176                                                    r = n32Tmp - SECUREC_MUL_TEN(q);
1177                                                    n32Tmp = (r > 9) ? (q + 1) : q; /* fast div  magic 9 */
1178                                                } while (n32Tmp != 0);
1179                                            } SECUREC_WHILE_ZERO;
1180                                            break;
1181#endif
1182                                        default:
1183                                            break;
1184                                    }   /* end switch */
1185                                } else {
1186                                    /* the value to be converted is greater than 4G */
1187#if defined(SECUREC_VXWORKS_VERSION_5_4)
1188                                    do {
1189                                        SecUnsignedInt32 digit = 0; /* ascii value of digit */
1190                                        SecUnsignedInt64 quotient = 0;
1191                                        if (SecU64Div32(number,(SecUnsignedInt32)radix, &quotient, &digit) != 0) {
1192                                            noOutput = 1;
1193                                            break;
1194                                        }
1195                                        *--formatBuf.str = digits[digit];
1196                                        number = quotient;
1197                                    } while (number != 0);
1198#else
1199                                    switch (radix) {
1200                                        /* the compiler will optimize div 10 */
1201                                        case SECUREC_RADIX_DECIMAL:
1202                                            SECUREC_SPECIAL_QWORD_BASE10(number);
1203                                            break;
1204                                        case SECUREC_RADIX_OCTAL:
1205                                            SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL);
1206                                            break;
1207                                        case SECUREC_RADIX_HEX:
1208                                            SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX);
1209                                            break;
1210                                        default:
1211                                            break;
1212                                    }
1213#endif
1214                                }
1215#endif
1216
1217                            }
1218                            /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */
1219                            textLen = (int)(size_t)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str);
1220                            if (formatAttr.precision > textLen) {
1221                                int ii;
1222                                for (ii = 0; ii < formatAttr.precision - textLen; ++ii) {
1223                                    *--formatBuf.str = '0';
1224                                }
1225                                textLen = formatAttr.precision;
1226                            }
1227
1228                            /* Force a leading zero if FORCEOCTAL flag set */
1229                            if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) &&
1230                                (textLen == 0 || formatBuf.str[0] != '0')) {
1231                                *--formatBuf.str = '0';
1232                                ++textLen;  /* add a zero */
1233                            }
1234                        } SECUREC_WHILE_ZERO;
1235                        break;
1236                    default:
1237                        break;
1238                }
1239
1240                while (noOutput < 1) {
1241                    if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1242                        if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) {
1243                            /* prefix is a '-' */
1244                            prefix[0] = SECUREC_CHAR('-');
1245                            prefixLen = 1;
1246                        } else if (formatAttr.flags & SECUREC_FLAG_SIGN) {
1247                            /* prefix is '+' */
1248                            prefix[0] = SECUREC_CHAR('+');
1249                            prefixLen = 1;
1250                        } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) {
1251                            /* prefix is ' ' */
1252                            prefix[0] = SECUREC_CHAR(' ');
1253                            prefixLen = 1;
1254                        }
1255                    }
1256
1257#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX))
1258                    if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (textLen == 0)) {
1259                        formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1260                        formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1];
1261                        *formatBuf.str-- = '\0';
1262                        *formatBuf.str-- = ')';
1263                        *formatBuf.str-- = 'l';
1264                        *formatBuf.str-- = 'i';
1265                        *formatBuf.str-- = 'n';
1266                        *formatBuf.str = '(';
1267                        textLen = 5; /* length of (nil) is 5 */
1268                    }
1269#endif
1270
1271                    /* calculate amount of padding */
1272                    padding = (formatAttr.fldWidth - textLen) - prefixLen;
1273
1274                    /* put out the padding, prefix, and text, in the correct order */
1275
1276                    if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) {
1277                        /* pad on left with blanks */
1278                        if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) {
1279                            /* char * cast to wchar * */
1280                            SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1281                        } else {
1282                            SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1283                        }
1284                    }
1285
1286                    /* write prefix */
1287                    if (prefixLen > 0) {
1288                        SecChar *pPrefix = prefix;
1289                        if (SECUREC_IS_REST_BUF_ENOUGH(stream, prefixLen)) {
1290                            /* max prefix len is 2, use loop copy */ /* char * cast to wchar * in WCHAR version */
1291                            SECUREC_SAFE_WRITE_STR_OPT(pPrefix, prefixLen, stream, &charsOut);
1292                        } else {
1293                            SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut);
1294                        }
1295                    }
1296
1297                    if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT)
1298                        && padding > 0) {
1299                        /* write leading zeros */
1300                        if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) {
1301                            /* char * cast to wchar * */
1302                            SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut);
1303                        } else {
1304                            SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut);
1305                        }
1306                    }
1307
1308                    /* write text */
1309#ifndef SECUREC_FOR_WCHAR
1310                    if (formatAttr.bufferIsWide != 0 && (textLen > 0)) {
1311#if SECUREC_HAVE_WCTOMB
1312                        wchar_t *p = formatBuf.wStr;
1313                        int count = textLen;
1314                        while (count > 0) {
1315                            char tmpBuf[SECUREC_MB_LEN + 1];
1316                            SECUREC_MASK_MSVC_CRT_WARNING
1317                            int retVal = wctomb(tmpBuf, *p);
1318                            SECUREC_END_MASK_MSVC_CRT_WARNING
1319                            if (retVal <= 0) {
1320                                charsOut = -1;
1321                                break;
1322                            }
1323                            SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut);
1324                            --count;
1325                            ++p;
1326                        }
1327#else
1328                        charsOut = -1;
1329                        break;
1330#endif
1331                    } else {
1332                        if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) {
1333                            SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut);
1334                        } else {
1335                            SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut);
1336                        }
1337                    }
1338#else /* SECUREC_FOR_WCHAR */
1339                    if (formatAttr.bufferIsWide == 0 && textLen > 0) {
1340#if SECUREC_HAVE_MBTOWC
1341                        int count = textLen;
1342                        char *p = formatBuf.str;
1343
1344                        while (count > 0) {
1345                            wchar_t wChar = L'\0';
1346                            int retVal = mbtowc(&wChar, p, (size_t)MB_CUR_MAX);
1347                            if (retVal <= 0) {
1348                                charsOut = -1;
1349                                break;
1350                            }
1351                            SecWriteCharW(wChar, stream, &charsOut);
1352                            p += retVal;
1353                            count -= retVal;
1354                        }
1355#else
1356                        charsOut = -1;
1357                        break;
1358#endif
1359                    } else {
1360                        if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) {
1361                            /* char * cast to wchar * */
1362                            SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut);
1363                        } else {
1364                            SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut);
1365                        }
1366                    }
1367#endif /* SECUREC_FOR_WCHAR */
1368
1369                    if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) {
1370                        /* pad on right with blanks */
1371                        if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) {
1372                            /* char * cast to wchar * */
1373                            SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1374                        } else {
1375                            SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1376                        }
1377                    }
1378                    break;
1379                }
1380#if SECUREC_ENABLE_SPRINTF_FLOAT
1381                if (floatBuf != NULL) {
1382                    SECUREC_FREE(floatBuf);
1383                    floatBuf = NULL;
1384                }
1385#endif
1386                break;
1387            case STAT_INVALID:
1388                return -1;
1389            default:
1390                return -1;          /* input format is wrong, directly return */
1391        }
1392    }
1393
1394    if (state != STAT_NORMAL && state != STAT_TYPE) {
1395        return -1;
1396    }
1397
1398    return charsOut;            /* the number of characters written */
1399}
1400#endif /* OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */
1401
1402