• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved.
3 * Licensed under Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 *          http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 * Description: Used by secureinput_a.c and secureinput_w.c to include.
12 *              This file provides a template function for ANSI and UNICODE compiling by
13 *              different type definition. The functions of SecInputS or
14 *              SecInputSW provides internal implementation for scanf family API, such as sscanf_s, fscanf_s.
15 * Create: 2014-02-25
16 * Notes: The formatted input processing results of integers on different platforms are different.
17 */
18/*
19 * [Standardize-exceptions] Use unsafe function: Performance-sensitive
20 * [reason] Always used in the performance critical path,
21 *          and sufficient input validation is performed before calling
22 */
23#ifndef INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
24#define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
25
26#if SECUREC_IN_KERNEL
27#if !defined(SECUREC_CTYPE_MACRO_ADAPT)
28#include <linux/ctype.h>
29#endif
30#else
31#if !defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT)
32#include <ctype.h>
33#ifdef SECUREC_FOR_WCHAR
34#include <wctype.h>             /* For iswspace */
35#endif
36#endif
37#endif
38
39#ifndef EOF
40#define EOF  (-1)
41#endif
42
43#define SECUREC_NUM_WIDTH_SHORT                 0
44#define SECUREC_NUM_WIDTH_INT                   1
45#define SECUREC_NUM_WIDTH_LONG                  2
46#define SECUREC_NUM_WIDTH_LONG_LONG             3 /* Also long double */
47
48#define SECUREC_BUFFERED_BLOK_SIZE              1024U
49
50#if defined(SECUREC_VXWORKS_PLATFORM) && !defined(va_copy) && !defined(__va_copy)
51/* The name is the same as system macro. */
52#define __va_copy(dest, src) do { \
53    size_t destSize_ = (size_t)sizeof(dest); \
54    size_t srcSize_ = (size_t)sizeof(src); \
55    if (destSize_ != srcSize_) { \
56        SECUREC_MEMCPY_WARP_OPT((dest), (src), sizeof(va_list)); \
57    } else { \
58        SECUREC_MEMCPY_WARP_OPT(&(dest), &(src), sizeof(va_list)); \
59    } \
60} SECUREC_WHILE_ZERO
61#endif
62
63#define SECUREC_MULTI_BYTE_MAX_LEN              6
64
65/* Compatibility macro name cannot be modifie */
66#ifndef UNALIGNED
67#if !(defined(_M_IA64)) && !(defined(_M_AMD64))
68#define UNALIGNED
69#else
70#define UNALIGNED __unaligned
71#endif
72#endif
73
74#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
75/* Max 64bit value is 0xffffffffffffffff */
76#define SECUREC_MAX_64BITS_VALUE                18446744073709551615ULL
77#define SECUREC_MAX_64BITS_VALUE_DIV_TEN        1844674407370955161ULL
78#define SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT 18446744073709551610ULL
79#define SECUREC_MIN_64BITS_NEG_VALUE            9223372036854775808ULL
80#define SECUREC_MAX_64BITS_POS_VALUE            9223372036854775807ULL
81#define SECUREC_MIN_32BITS_NEG_VALUE            2147483648UL
82#define SECUREC_MAX_32BITS_POS_VALUE            2147483647UL
83#define SECUREC_MAX_32BITS_VALUE                4294967295UL
84#define SECUREC_MAX_32BITS_VALUE_INC            4294967296UL
85#define SECUREC_MAX_32BITS_VALUE_DIV_TEN        429496729UL
86#define SECUREC_LONG_BIT_NUM                    ((unsigned int)(sizeof(long) << 3U))
87/* Use ULL to clean up cl6x compilation alerts */
88#define SECUREC_MAX_LONG_POS_VALUE              ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)) - 1)
89#define SECUREC_MIN_LONG_NEG_VALUE              ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)))
90
91/* Covert to long long to clean up cl6x compilation alerts */
92#define SECUREC_LONG_HEX_BEYOND_MAX(number)     (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0)
93#define SECUREC_LONG_OCTAL_BEYOND_MAX(number)   (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 3U)) > 0)
94
95#define SECUREC_QWORD_HEX_BEYOND_MAX(number)    (((number) >> (64U - 4U)) > 0)
96#define SECUREC_QWORD_OCTAL_BEYOND_MAX(number)  (((number) >> (64U - 3U)) > 0)
97
98#define SECUREC_LP64_BIT_WIDTH                  64
99#define SECUREC_LP32_BIT_WIDTH                  32
100
101#define SECUREC_CONVERT_IS_SIGNED(conv) ((conv) == 'd' || (conv) == 'i')
102#endif
103
104#define SECUREC_BRACE                           '{'     /* [ to { */
105#define SECUREC_FILED_WIDTH_ENOUGH(spec) ((spec)->widthSet == 0 || (spec)->width > 0)
106#define SECUREC_FILED_WIDTH_DEC(spec) do { \
107    if ((spec)->widthSet != 0) { \
108        --(spec)->width; \
109    } \
110} SECUREC_WHILE_ZERO
111
112#ifdef SECUREC_FOR_WCHAR
113/* Bits for all wchar, size is 65536/8, only supports wide characters with a maximum length of two bytes */
114#define SECUREC_BRACKET_TABLE_SIZE    8192
115#define SECUREC_EOF WEOF
116#define SECUREC_MB_LEN 16       /* Max. # bytes in multibyte char  ,see MB_LEN_MAX */
117#else
118/* Bits for all char, size is 256/8 */
119#define SECUREC_BRACKET_TABLE_SIZE    32
120#define SECUREC_EOF EOF
121#endif
122
123#if SECUREC_HAVE_WCHART
124#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \
125    ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN) || \
126    ((spec).isWCharOrLong > 0 && (spec).arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN))
127#else
128#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || (spec).arrayWidth > SECUREC_STRING_MAX_LEN)
129#endif
130
131#ifdef SECUREC_ON_64BITS
132/* Use 0xffffffffUL mask to pass integer as array length */
133#define SECUREC_GET_ARRAYWIDTH(argList) (((size_t)va_arg((argList), size_t)) & 0xffffffffUL)
134#else /* !SECUREC_ON_64BITS */
135#define SECUREC_GET_ARRAYWIDTH(argList) ((size_t)va_arg((argList), size_t))
136#endif
137
138typedef struct {
139#ifdef SECUREC_FOR_WCHAR
140    unsigned char *table; /* Default NULL */
141#else
142    unsigned char table[SECUREC_BRACKET_TABLE_SIZE]; /* Array length is large enough in application scenarios */
143#endif
144    unsigned char mask; /* Default 0 */
145} SecBracketTable;
146
147#ifdef SECUREC_FOR_WCHAR
148#define SECUREC_INIT_BRACKET_TABLE { NULL, 0 }
149#else
150#define SECUREC_INIT_BRACKET_TABLE { {0}, 0 }
151#endif
152
153#if SECUREC_ENABLE_SCANF_FLOAT
154typedef struct {
155    size_t floatStrTotalLen;       /* Initialization must be length of buffer in charater */
156    size_t floatStrUsedLen;        /* Store float string len */
157    SecChar *floatStr;             /* Initialization must point to buffer */
158    SecChar *allocatedFloatStr;    /* Initialization must be NULL  to store alloced point */
159    SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1];
160} SecFloatSpec;
161#endif
162
163#define SECUREC_NUMBER_STATE_DEFAULT 0U
164#define SECUREC_NUMBER_STATE_STARTED 1U
165
166typedef struct {
167    SecInt ch;            /* Char read from input */
168    int charCount;        /* Number of characters processed */
169    void *argPtr;         /* Variable parameter pointer, point to the end of the string */
170    size_t arrayWidth;    /* Length of pointer Variable parameter, in charaters */
171    SecUnsignedInt64 number64; /* Store input number64 value */
172    unsigned long number; /* Store input number32 value */
173    int numberWidth;      /* 0 = SHORT, 1 = int, > 1  long or L_DOUBLE */
174    int numberArgType;       /* 1 for 64-bit integer, 0 otherwise. use it as decode function index */
175    unsigned int negative;         /* 0 is positive */
176#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
177    unsigned int beyondMax;        /* Non-zero means beyond */
178#endif
179    unsigned int numberState; /* Identifies whether to start processing numbers, 1 is can input number */
180    int width;            /* Width number in format */
181    int widthSet;         /* 0 is not set width in format */
182    int convChr;          /* Lowercase format conversion characters */
183    int oriConvChr;       /* Store  original format conversion, convChr may change when parsing integers */
184    signed char isWCharOrLong;  /* -1/0 not wchar or long, 1 for wchar or long */
185    unsigned char suppress;     /* 0 is not have %* in format */
186} SecScanSpec;
187
188#ifdef SECUREC_FOR_WCHAR
189#define SECUREC_GETC fgetwc
190#define SECUREC_UN_GETC ungetwc
191/* Only supports wide characters with a maximum length of two bytes in format string */
192#define SECUREC_BRACKET_CHAR_MASK 0xffffU
193#else
194#define SECUREC_GETC fgetc
195#define SECUREC_UN_GETC ungetc
196#define SECUREC_BRACKET_CHAR_MASK 0xffU
197#endif
198
199#define SECUREC_CHAR_SIZE ((unsigned int)(sizeof(SecChar)))
200/* To avoid 648, mask high bit: 0x00ffffff 0x0000ffff or 0x00000000 */
201#define SECUREC_CHAR_MASK_HIGH (((((((((unsigned int)(-1) >> SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
202    SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
203    SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
204    SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE)
205
206/* For char is 0xff, wcahr_t is 0xffff or 0xffffffff. */
207#define SECUREC_CHAR_MASK (~((((((((((unsigned int)(-1) & SECUREC_CHAR_MASK_HIGH) << \
208    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
209    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
210    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
211    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE))
212
213/* According wchar_t has multiple bytes, so use sizeof */
214#define SECUREC_GET_CHAR(stream, outCh) do { \
215    if ((stream)->count >= sizeof(SecChar)) { \
216        *(outCh) = (SecInt)(SECUREC_CHAR_MASK & \
217            (unsigned int)(int)(*((const SecChar *)(const void *)(stream)->cur))); \
218        (stream)->cur += sizeof(SecChar); \
219        (stream)->count -= sizeof(SecChar); \
220    } else { \
221        *(outCh) = SECUREC_EOF; \
222    } \
223} SECUREC_WHILE_ZERO
224
225#define SECUREC_UN_GET_CHAR(stream) do { \
226    if ((stream)->cur > (stream)->base) { \
227        (stream)->cur -= sizeof(SecChar); \
228        (stream)->count += sizeof(SecChar); \
229    } \
230} SECUREC_WHILE_ZERO
231
232/* Convert wchar_t to int and then to unsigned int  to keep data clearing warning */
233#define SECUREC_TO_LOWERCASE(chr) ((int)((unsigned int)(int)(chr) | (unsigned int)('a' - 'A')))
234
235/* Record a flag for each bit */
236#define SECUREC_BRACKET_INDEX(x)  ((unsigned int)(x) >> 3U)
237#define SECUREC_BRACKET_VALUE(x)  ((unsigned char)(1U << ((unsigned int)(x) & 7U)))
238#if SECUREC_IN_KERNEL
239#define SECUREC_CONVERT_IS_UNSIGNED(conv) ((conv) == 'x' || (conv) == 'o' || (conv) == 'u')
240#endif
241
242/*
243 * Set char in %[xxx] into table, only supports wide characters with a maximum length of two bytes
244 */
245SECUREC_INLINE void SecBracketSetBit(unsigned char *table, SecUnsignedChar ch)
246{
247    unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
248    unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
249    /* Do not use   |=   optimize this code, it will cause compiling warning */
250    table[tableIndex] = (unsigned char)(table[tableIndex] | tableValue);
251}
252
253SECUREC_INLINE void SecBracketSetBitRange(unsigned char *table, SecUnsignedChar startCh, SecUnsignedChar endCh)
254{
255    SecUnsignedChar expCh;
256    /* %[a-z] %[a-a] Format %[a-\xff] end is 0xFF, condition (expCh <= endChar) cause dead loop */
257    for (expCh = startCh; expCh < endCh; ++expCh) {
258        SecBracketSetBit(table, expCh);
259    }
260    SecBracketSetBit(table, endCh);
261}
262/*
263 * Determine whether the expression can be satisfied
264 */
265SECUREC_INLINE int SecCanInputForBracket(int convChr, SecInt ch, const SecBracketTable *bracketTable)
266{
267    unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
268    unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
269#ifdef SECUREC_FOR_WCHAR
270    if (((unsigned int)(int)ch & (~(SECUREC_BRACKET_CHAR_MASK))) != 0) {
271        /* The value of the wide character exceeds the size of two bytes */
272        return 0;
273    }
274    return (int)(convChr == SECUREC_BRACE &&
275        (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0);
276#else
277    return (int)(convChr == SECUREC_BRACE &&
278        (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0);
279#endif
280}
281
282/*
283 * String input ends when blank character is encountered
284 */
285SECUREC_INLINE int SecCanInputString(int convChr, SecInt ch)
286{
287    return (int)(convChr == 's' &&
288        (!(ch >= SECUREC_CHAR('\t') && ch <= SECUREC_CHAR('\r')) && ch != SECUREC_CHAR(' ')));
289}
290
291/*
292 * Can input a character when format is %c
293 */
294SECUREC_INLINE int SecCanInputCharacter(int convChr)
295{
296    return (int)(convChr == 'c');
297}
298
299/*
300 * Determine if it is a 64-bit pointer  function
301 * Return 0 is not ,1 is 64bit pointer
302 */
303SECUREC_INLINE int SecNumberArgType(size_t sizeOfVoidStar)
304{
305    /* Point size is 4 or 8 , Under the 64 bit system, the value not 0 */
306    /* To clear e778 */
307    if ((sizeOfVoidStar & sizeof(SecInt64)) != 0) {
308        return 1;
309    }
310    return 0;
311}
312SECUREC_INLINE int SecIsDigit(SecInt ch);
313SECUREC_INLINE int SecIsXdigit(SecInt ch);
314SECUREC_INLINE int SecIsSpace(SecInt ch);
315SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter);
316SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter);
317SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter);
318
319#if SECUREC_ENABLE_SCANF_FLOAT
320
321/*
322 * Convert a floating point string to a floating point number
323 */
324SECUREC_INLINE int SecAssignNarrowFloat(const char *floatStr, const SecScanSpec *spec)
325{
326    char *endPtr = NULL;
327    double d;
328#if SECUREC_SUPPORT_STRTOLD
329    if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG_LONG) {
330        long double d2 = strtold(floatStr, &endPtr);
331        if (endPtr == floatStr) {
332            return -1;
333        }
334        *(long double UNALIGNED *)(spec->argPtr) = d2;
335        return 0;
336    }
337#endif
338    d = strtod(floatStr, &endPtr);
339    /* cannot detect if endPtr points to the end of floatStr,because strtod handles only two characters for 1.E */
340    if (endPtr == floatStr) {
341        return -1;
342    }
343    if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) {
344        *(double UNALIGNED *)(spec->argPtr) = (double)d;
345    } else {
346        *(float UNALIGNED *)(spec->argPtr) = (float)d;
347    }
348    return 0;
349}
350
351#ifdef SECUREC_FOR_WCHAR
352/*
353 * Convert a floating point wchar string to a floating point number
354 * Success  ret 0
355 */
356SECUREC_INLINE int SecAssignWideFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
357{
358    int retVal;
359    /* Convert float string */
360    size_t mbsLen;
361    size_t tempFloatStrLen = (size_t)(floatSpec->floatStrUsedLen + 1) * sizeof(wchar_t);
362    char *tempFloatStr = (char *)SECUREC_MALLOC(tempFloatStrLen);
363    if (tempFloatStr == NULL) {
364        return -1;
365    }
366    tempFloatStr[0] = '\0';
367    SECUREC_MASK_MSVC_CRT_WARNING
368    mbsLen = wcstombs(tempFloatStr, floatSpec->floatStr, tempFloatStrLen - 1);
369    SECUREC_END_MASK_MSVC_CRT_WARNING
370    /* This condition must satisfy mbsLen is not -1 */
371    if (mbsLen >= tempFloatStrLen) {
372        SECUREC_FREE(tempFloatStr);
373        return -1;
374    }
375    tempFloatStr[mbsLen] = '\0';
376    retVal = SecAssignNarrowFloat(tempFloatStr, spec);
377    SECUREC_FREE(tempFloatStr);
378    return retVal;
379}
380#endif
381
382SECUREC_INLINE int SecAssignFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
383{
384#ifdef SECUREC_FOR_WCHAR
385    return SecAssignWideFloat(floatSpec, spec);
386#else
387    return SecAssignNarrowFloat(floatSpec->floatStr, spec);
388#endif
389}
390
391/*
392 * Init SecFloatSpec before parse format
393 */
394SECUREC_INLINE void SecInitFloatSpec(SecFloatSpec *floatSpec)
395{
396    floatSpec->floatStr = floatSpec->buffer;
397    floatSpec->allocatedFloatStr = NULL;
398    floatSpec->floatStrTotalLen = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]);
399    floatSpec->floatStrUsedLen = 0;
400}
401
402SECUREC_INLINE void SecFreeFloatSpec(SecFloatSpec *floatSpec, int *doneCount)
403{
404    /* 2014.3.6 add, clear the stack data */
405    if (memset_s(floatSpec->buffer, sizeof(floatSpec->buffer), 0, sizeof(floatSpec->buffer)) != EOK) {
406        *doneCount = 0; /* This code just to meet the coding requirements */
407    }
408    /* The pFloatStr can be alloced in SecExtendFloatLen function, clear and free it */
409    if (floatSpec->allocatedFloatStr != NULL) {
410        size_t bufferSize = floatSpec->floatStrTotalLen * sizeof(SecChar);
411        if (memset_s(floatSpec->allocatedFloatStr, bufferSize, 0, bufferSize) != EOK) {
412            *doneCount = 0; /* This code just to meet the coding requirements */
413        }
414        SECUREC_FREE(floatSpec->allocatedFloatStr);
415        floatSpec->allocatedFloatStr = NULL;
416        floatSpec->floatStr = NULL;
417    }
418}
419
420/*
421 * Splice floating point string
422 * Return 0 OK
423 */
424SECUREC_INLINE int SecExtendFloatLen(SecFloatSpec *floatSpec)
425{
426    if (floatSpec->floatStrUsedLen >= floatSpec->floatStrTotalLen) {
427        /* Buffer size is len x sizeof(SecChar) */
428        size_t oriSize = floatSpec->floatStrTotalLen * sizeof(SecChar);
429        /* Add one character to clear tool warning */
430        size_t nextSize = (oriSize * 2) + sizeof(SecChar); /* Multiply 2 to extend buffer size */
431
432        /* Prevents integer overflow, the maximum length of SECUREC_MAX_WIDTH_LEN is enough */
433        if (nextSize <= (size_t)SECUREC_MAX_WIDTH_LEN) {
434            void *nextBuffer = (void *)SECUREC_MALLOC(nextSize);
435            if (nextBuffer == NULL) {
436                return -1;
437            }
438            if (memcpy_s(nextBuffer, nextSize, floatSpec->floatStr, oriSize) != EOK) {
439                SECUREC_FREE(nextBuffer);   /* This is a dead code, just to meet the coding requirements */
440                return -1;
441            }
442            /* Clear old buffer memory */
443            if (memset_s(floatSpec->floatStr, oriSize, 0, oriSize) != EOK) {
444                SECUREC_FREE(nextBuffer);   /* This is a dead code, just to meet the coding requirements */
445                return -1;
446            }
447            /* Free old allocated buffer */
448            if (floatSpec->allocatedFloatStr != NULL) {
449                SECUREC_FREE(floatSpec->allocatedFloatStr);
450            }
451            floatSpec->allocatedFloatStr = (SecChar *)(nextBuffer);    /* Use to clear free on stack warning */
452            floatSpec->floatStr = (SecChar *)(nextBuffer);
453            floatSpec->floatStrTotalLen = nextSize / sizeof(SecChar); /* Get buffer total len in character */
454            return 0;
455        }
456        return -1; /* Next size is beyond max */
457    }
458    return 0;
459}
460
461/* Do not use localeconv()->decimal_pointif  only support  '.' */
462SECUREC_INLINE int SecIsFloatDecimal(SecChar ch)
463{
464    return (int)(ch == SECUREC_CHAR('.'));
465}
466
467SECUREC_INLINE int SecInputFloatSign(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
468{
469    if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) {
470        return 0;
471    }
472    spec->ch = SecGetChar(stream, &(spec->charCount));
473    if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
474        SECUREC_FILED_WIDTH_DEC(spec); /* Make sure the count after un get char is correct */
475        if (spec->ch == SECUREC_CHAR('-')) {
476            floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('-');
477            ++floatSpec->floatStrUsedLen;
478            if (SecExtendFloatLen(floatSpec) != 0) {
479                return -1;
480            }
481        }
482    } else {
483        SecUnGetChar(spec->ch, stream, &(spec->charCount));
484    }
485    return 0;
486}
487
488SECUREC_INLINE int SecInputFloatDigit(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
489{
490    /* Now get integral part */
491    while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
492        spec->ch = SecGetChar(stream, &(spec->charCount));
493        if (SecIsDigit(spec->ch) == 0) {
494            SecUnGetChar(spec->ch, stream, &(spec->charCount));
495            return 0;
496        }
497        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
498        spec->numberState = SECUREC_NUMBER_STATE_STARTED;
499        floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch;
500        ++floatSpec->floatStrUsedLen;
501        if (SecExtendFloatLen(floatSpec) != 0) {
502            return -1;
503        }
504    }
505    return 0;
506}
507
508/*
509* Scan value of exponent.
510* Return 0 OK
511*/
512SECUREC_INLINE int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
513{
514    if (SecInputFloatSign(stream, spec, floatSpec) == -1) {
515        return -1;
516    }
517    if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
518        return -1;
519    }
520    return 0;
521}
522
523SECUREC_INLINE int SecInputFloatFractional(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
524{
525    if (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
526        spec->ch = SecGetChar(stream, &(spec->charCount));
527        if (SecIsFloatDecimal((SecChar)spec->ch) == 0) {
528            SecUnGetChar(spec->ch, stream, &(spec->charCount));
529            return 0;
530        }
531        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
532        /* Now check for decimal */
533        floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch;
534        ++floatSpec->floatStrUsedLen;
535        if (SecExtendFloatLen(floatSpec) != 0) {
536            return -1;
537        }
538        if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
539            return -1;
540        }
541    }
542    return 0;
543}
544
545SECUREC_INLINE int SecInputFloatExponent(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
546{
547    /* Now get exponent part */
548    if (spec->numberState == SECUREC_NUMBER_STATE_STARTED && SECUREC_FILED_WIDTH_ENOUGH(spec)) {
549        spec->ch = SecGetChar(stream, &(spec->charCount));
550        if (spec->ch != SECUREC_CHAR('e') && spec->ch != SECUREC_CHAR('E')) {
551            SecUnGetChar(spec->ch, stream, &(spec->charCount));
552            return 0;
553        }
554        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
555        floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('e');
556        ++floatSpec->floatStrUsedLen;
557        if (SecExtendFloatLen(floatSpec) != 0) {
558            return -1;
559        }
560        if (SecInputFloatE(stream, spec, floatSpec) != 0) {
561            return -1;
562        }
563    }
564    return 0;
565}
566
567/*
568* Scan %f.
569* Return 0 OK
570*/
571SECUREC_INLINE int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
572{
573    floatSpec->floatStrUsedLen = 0;
574
575    /* The following code sequence is strict */
576    if (SecInputFloatSign(stream, spec, floatSpec) != 0) {
577        return -1;
578    }
579    if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
580        return -1;
581    }
582    if (SecInputFloatFractional(stream, spec, floatSpec) != 0) {
583        return -1;
584    }
585    if (SecInputFloatExponent(stream, spec, floatSpec) != 0) {
586        return -1;
587    }
588
589    /* Make sure  have a string terminator, buffer is large enough */
590    floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0');
591    if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) {
592        return 0;
593    }
594    return -1;
595}
596#endif
597
598#if (!defined(SECUREC_FOR_WCHAR) && SECUREC_HAVE_WCHART && SECUREC_HAVE_MBTOWC) || \
599    (!defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION))
600/* only multi-bytes string need isleadbyte() function */
601SECUREC_INLINE int SecIsLeadByte(SecInt ch)
602{
603    unsigned int c = (unsigned int)ch;
604#if !(defined(_MSC_VER) || defined(_INC_WCTYPE))
605    return (int)(c & 0x80U); /* Use bitwise operation to check if the most significant bit is 1 */
606#else
607    return (int)isleadbyte((int)(c & 0xffU)); /* Use bitwise operations to limit character values to valid ranges */
608#endif
609}
610#endif
611
612/*
613 * Parsing whether it is a wide character
614 */
615SECUREC_INLINE void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec)
616{
617    if (spec->isWCharOrLong != 0) {
618        /* Wide character identifiers have been explicitly set by l or h flag */
619        return;
620    }
621
622    /* Set default flag */
623#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT)
624    spec->isWCharOrLong = 1;  /* On windows wide char version %c %s %[ is wide char */
625#else
626    spec->isWCharOrLong = -1; /* On linux all version %c %s %[ is multi char */
627#endif
628
629    if (ch == SECUREC_CHAR('C') || ch == SECUREC_CHAR('S')) {
630#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT)
631        spec->isWCharOrLong = -1; /* On windows wide char version %C %S is multi char */
632#else
633        spec->isWCharOrLong = 1;  /* On linux all version %C %S is wide char */
634#endif
635    }
636
637    return;
638}
639/*
640 * Decode  %l %ll
641 */
642SECUREC_INLINE void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec)
643{
644    const SecUnsignedChar *fmt = *format;
645    if (*(fmt + 1) == SECUREC_CHAR('l')) {
646        spec->numberArgType = 1;
647        spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
648        ++fmt;
649    } else {
650        spec->numberWidth = SECUREC_NUM_WIDTH_LONG;
651#if defined(SECUREC_ON_64BITS) && !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
652        /* On window 64 system sizeof long is 32bit */
653        spec->numberArgType = 1;
654#endif
655        spec->isWCharOrLong = 1;
656    }
657    *format = fmt;
658}
659
660/*
661 * Decode  %I %I43 %I64 %Id %Ii %Io ...
662 * Set finishFlag to  1  finish Flag
663 */
664SECUREC_INLINE void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
665{
666    const SecUnsignedChar *fmt = *format;
667    if ((*(fmt + 1) == SECUREC_CHAR('6')) &&
668        (*(fmt + 2) == SECUREC_CHAR('4'))) { /* Offset 2 for I64 */
669        spec->numberArgType = 1;
670        *format = *format + 2; /* Add 2 to skip I64 point to '4' next loop will inc */
671    } else if ((*(fmt + 1) == SECUREC_CHAR('3')) &&
672                (*(fmt + 2) == SECUREC_CHAR('2'))) { /* Offset 2 for I32 */
673        *format = *format + 2; /* Add 2 to skip I32 point to '2' next loop will inc */
674    } else if ((*(fmt + 1) == SECUREC_CHAR('d')) ||
675                (*(fmt + 1) == SECUREC_CHAR('i')) ||
676                (*(fmt + 1) == SECUREC_CHAR('o')) ||
677                (*(fmt + 1) == SECUREC_CHAR('x')) ||
678                (*(fmt + 1) == SECUREC_CHAR('X'))) {
679        spec->numberArgType = SecNumberArgType(sizeof(void *));
680    } else {
681        /* For %I */
682        spec->numberArgType = SecNumberArgType(sizeof(void *));
683        *finishFlag = 1;
684    }
685}
686
687SECUREC_INLINE int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec)
688{
689    const SecUnsignedChar *fmt = *format;
690    while (SecIsDigit((SecInt)(int)(*fmt)) != 0) {
691        spec->widthSet = 1;
692        if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(spec->width)) {
693            return -1;
694        }
695        spec->width = (int)SECUREC_MUL_TEN((unsigned int)spec->width) + (unsigned char)(*fmt - SECUREC_CHAR('0'));
696        ++fmt;
697    }
698    *format = fmt;
699    return 0;
700}
701
702/*
703 * Init default flags for each format. do not init ch this variable is context-dependent
704 */
705SECUREC_INLINE void SecSetDefaultScanSpec(SecScanSpec *spec)
706{
707    /* The ch and charCount member variables cannot be initialized here */
708    spec->argPtr = NULL;
709    spec->arrayWidth = 0;
710    spec->number64 = 0;
711    spec->number = 0;
712    spec->numberWidth = SECUREC_NUM_WIDTH_INT;    /* 0 = SHORT, 1 = int, > 1  long or L_DOUBLE */
713    spec->numberArgType = 0;                         /* 1 for 64-bit integer, 0 otherwise */
714    spec->width = 0;
715    spec->widthSet = 0;
716    spec->convChr = 0;
717    spec->oriConvChr = 0;
718    spec->isWCharOrLong = 0;
719    spec->suppress = 0;
720#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
721    spec->beyondMax = 0;
722#endif
723    spec->negative = 0;
724    spec->numberState = SECUREC_NUMBER_STATE_DEFAULT;
725}
726
727/*
728 * Decode qualifier %I %L %h ...
729 * Set finishFlag to  1  finish Flag
730 */
731SECUREC_INLINE void  SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
732{
733    switch (**format) {
734        case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */
735        case SECUREC_CHAR('N'):
736            break;
737        case SECUREC_CHAR('h'):
738            --spec->numberWidth; /* The h for SHORT , hh for CHAR */
739            spec->isWCharOrLong = -1;
740            break;
741#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
742        case SECUREC_CHAR('j'):
743            spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;  /* For intmax_t or uintmax_t */
744            spec->numberArgType = 1;
745            break;
746        case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */
747#endif
748#if SECUREC_IN_KERNEL
749        case SECUREC_CHAR('Z'): /* fall-through */ /* FALLTHRU */
750#endif
751        case SECUREC_CHAR('z'):
752#ifdef SECUREC_ON_64BITS
753            spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
754            spec->numberArgType = 1;
755#else
756            spec->numberWidth = SECUREC_NUM_WIDTH_LONG;
757#endif
758            break;
759        case SECUREC_CHAR('L'):    /* For long double */ /* fall-through */ /* FALLTHRU */
760        case SECUREC_CHAR('q'):
761            spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
762            spec->numberArgType = 1;
763            break;
764        case SECUREC_CHAR('l'):
765            SecDecodeScanQualifierL(format, spec);
766            break;
767        case SECUREC_CHAR('w'):
768            spec->isWCharOrLong = 1;
769            break;
770        case SECUREC_CHAR('*'):
771            spec->suppress = 1;
772            break;
773        case SECUREC_CHAR('I'):
774            SecDecodeScanQualifierI(format, spec, finishFlag);
775            break;
776        default:
777            *finishFlag = 1;
778            break;
779    }
780}
781/*
782 * Decode width and qualifier in format
783 */
784SECUREC_INLINE int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec)
785{
786    const SecUnsignedChar *fmt = *format;
787    int finishFlag = 0;
788
789    do {
790        ++fmt; /*  First skip % , next  seek fmt */
791        /* May %*6d , so put it inside the loop */
792        if (SecDecodeScanWidth(&fmt, spec) != 0) {
793            return -1;
794        }
795        SecDecodeScanQualifier(&fmt, spec, &finishFlag);
796    } while (finishFlag == 0);
797    *format = fmt;
798    return 0;
799}
800
801/*
802 * Judging whether a zeroing buffer is needed according to different formats
803 */
804SECUREC_INLINE int SecDecodeClearFormat(const SecUnsignedChar *format, int *convChr)
805{
806    const SecUnsignedChar *fmt = format;
807    /* To lowercase */
808    int ch = SECUREC_TO_LOWERCASE(*fmt);
809    if (!(ch == 'c' || ch == 's' || ch == SECUREC_BRACE)) {
810        return -1;     /* First argument is not a string type */
811    }
812    if (ch == SECUREC_BRACE) {
813#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
814        if (*fmt == SECUREC_CHAR('{')) {
815            return -1;
816        }
817#endif
818        ++fmt;
819        if (*fmt == SECUREC_CHAR('^')) {
820            ++fmt;
821        }
822        if (*fmt == SECUREC_CHAR(']')) {
823            ++fmt;
824        }
825        while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
826            ++fmt;
827        }
828        if (*fmt == SECUREC_CHAR('\0')) {
829            return -1; /* Trunc'd format string */
830        }
831    }
832    *convChr = ch;
833    return 0;
834}
835
836/*
837 * Add L'\0' for wchar string , add '\0' for char string
838 */
839SECUREC_INLINE void SecAddEndingZero(void *ptr, const SecScanSpec *spec)
840{
841    if (spec->suppress == 0) {
842        *(char *)ptr = '\0';
843#if SECUREC_HAVE_WCHART
844        if (spec->isWCharOrLong > 0) {
845            *(wchar_t UNALIGNED *)ptr = L'\0';
846        }
847#endif
848    }
849}
850
851SECUREC_INLINE void SecDecodeClearArg(SecScanSpec *spec, va_list argList)
852{
853    va_list argListSave; /* Backup for argList value, this variable don't need initialized */
854    (void)SECUREC_MEMSET_FUNC_OPT(&argListSave, 0, sizeof(va_list)); /* To clear e530 argListSave not initialized */
855#if defined(va_copy)
856    va_copy(argListSave, argList);
857#elif defined(__va_copy)        /* For vxworks */
858    __va_copy(argListSave, argList);
859#else
860    argListSave = argList;
861#endif
862    spec->argPtr = (void *)va_arg(argListSave, void *);
863    /* Get the next argument, size of the array in characters */
864    /* Use 0xffffffffUL mask to Support  pass integer as array length */
865    spec->arrayWidth = ((size_t)(va_arg(argListSave, size_t))) & 0xffffffffUL;
866    va_end(argListSave);
867    /* To clear e438 last value assigned not used , the compiler will optimize this code */
868    (void)argListSave;
869}
870
871#ifdef SECUREC_FOR_WCHAR
872/*
873 *  Clean up the first %s %c buffer to zero for wchar version
874 */
875void SecClearDestBufW(const wchar_t *buffer, const wchar_t *format, va_list argList)
876#else
877/*
878 *  Clean up the first %s %c buffer to zero for char version
879 */
880void SecClearDestBuf(const char *buffer, const char *format, va_list argList)
881#endif
882{
883    SecScanSpec spec;
884    int convChr = 0;
885    const SecUnsignedChar *fmt = (const SecUnsignedChar *)format;
886
887    /* Find first % */
888    while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR('%')) {
889        ++fmt;
890    }
891    if (*fmt == SECUREC_CHAR('\0')) {
892        return;
893    }
894
895    SecSetDefaultScanSpec(&spec);
896    if (SecDecodeScanFlag(&fmt, &spec) != 0) {
897        return;
898    }
899
900    /* Update wchar flag for %S %C */
901    SecUpdateWcharFlagByType(*fmt, &spec);
902    if (spec.suppress != 0) {
903        return;
904    }
905
906    if (SecDecodeClearFormat(fmt, &convChr) != 0) {
907        return;
908    }
909
910    if (*buffer != SECUREC_CHAR('\0') && convChr != 's') {
911        /*
912         * When buffer not empty just clear %s.
913         * Example call sscanf by  argment of (" \n", "%s", s, sizeof(s))
914         */
915        return;
916    }
917
918    SecDecodeClearArg(&spec, argList);
919    /* There is no need to judge the upper limit */
920    if (spec.arrayWidth == 0 || spec.argPtr == NULL) {
921        return;
922    }
923    /* Clear one char */
924    SecAddEndingZero(spec.argPtr, &spec);
925    return;
926}
927
928/*
929 *  Assign number  to output buffer
930 */
931SECUREC_INLINE void SecAssignNumber(const SecScanSpec *spec)
932{
933    void *argPtr = spec->argPtr;
934    if (spec->numberArgType != 0) {
935#if defined(SECUREC_VXWORKS_PLATFORM)
936#if defined(SECUREC_VXWORKS_PLATFORM_COMP)
937        *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64);
938#else
939        /* Take number64 as unsigned number unsigned to int clear Compile warning */
940        *(SecInt64 UNALIGNED *)argPtr = *(SecUnsignedInt64 *)(&(spec->number64));
941#endif
942#else
943        /* Take number64 as unsigned number */
944        *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64);
945#endif
946        return;
947    }
948    if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) {
949        /* Take number as unsigned number */
950        *(long UNALIGNED *)argPtr = (long)(spec->number);
951    } else if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
952        *(int UNALIGNED *)argPtr = (int)(spec->number);
953    } else if (spec->numberWidth == SECUREC_NUM_WIDTH_SHORT) {
954        /* Take number as unsigned number */
955        *(short UNALIGNED *)argPtr = (short)(spec->number);
956    } else {  /* < 0 for hh format modifier */
957        /* Take number as unsigned number */
958        *(char UNALIGNED *)argPtr = (char)(spec->number);
959    }
960}
961
962#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
963/*
964 *  Judge the long bit width
965 */
966SECUREC_INLINE int SecIsLongBitEqual(int bitNum)
967{
968    return (int)((unsigned int)bitNum == SECUREC_LONG_BIT_NUM);
969}
970#endif
971
972/*
973 * Convert hexadecimal characters to decimal value
974 */
975SECUREC_INLINE int SecHexValueOfChar(SecInt ch)
976{
977    /* Use isdigit Causing tool false alarms */
978    return (int)((ch >= '0' && ch <= '9') ? ((unsigned char)ch - '0') :
979            ((((unsigned char)ch | (unsigned char)('a' - 'A')) - ('a')) + 10)); /* Adding 10 is to hex value */
980}
981
982/*
983 * Parse decimal character to integer for 32bit .
984 */
985static void SecDecodeNumberDecimal(SecScanSpec *spec)
986{
987#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
988    unsigned long decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN;
989#ifdef SECUREC_ON_64BITS
990    if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
991        decimalEdge = (unsigned long)SECUREC_MAX_64BITS_VALUE_DIV_TEN;
992    }
993#endif
994    if (spec->number > decimalEdge) {
995        spec->beyondMax = 1;
996    }
997#endif
998    spec->number = SECUREC_MUL_TEN(spec->number);
999#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1000    if (spec->number == SECUREC_MUL_TEN(decimalEdge)) {
1001        /* This code is specially converted to unsigned long type for compatibility */
1002        SecUnsignedInt64 number64As = (unsigned long)SECUREC_MAX_64BITS_VALUE - spec->number;
1003        if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) {
1004            spec->beyondMax = 1;
1005        }
1006    }
1007#endif
1008    spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
1009}
1010
1011/*
1012 * Parse Hex character to integer for 32bit .
1013 */
1014static void SecDecodeNumberHex(SecScanSpec *spec)
1015{
1016#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1017    if (SECUREC_LONG_HEX_BEYOND_MAX(spec->number)) {
1018        spec->beyondMax = 1;
1019    }
1020#endif
1021    spec->number = SECUREC_MUL_SIXTEEN(spec->number);
1022    spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(spec->ch);
1023}
1024
1025/*
1026 * Parse Octal character to integer for 32bit .
1027 */
1028static void SecDecodeNumberOctal(SecScanSpec *spec)
1029{
1030#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1031    if (SECUREC_LONG_OCTAL_BEYOND_MAX(spec->number)) {
1032        spec->beyondMax = 1;
1033    }
1034#endif
1035    spec->number = SECUREC_MUL_EIGHT(spec->number);
1036    spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
1037}
1038
1039#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1040/* Compatible with integer negative values other than int */
1041SECUREC_INLINE void SecFinishNumberNegativeOther(SecScanSpec *spec)
1042{
1043    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
1044        if (spec->number > SECUREC_MIN_LONG_NEG_VALUE) {
1045            spec->number = SECUREC_MIN_LONG_NEG_VALUE;
1046        } else {
1047            spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
1048        }
1049        if (spec->beyondMax != 0) {
1050            if (spec->numberWidth < SECUREC_NUM_WIDTH_INT) {
1051                spec->number = 0;
1052            }
1053            if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG) {
1054                spec->number = SECUREC_MIN_LONG_NEG_VALUE;
1055            }
1056        }
1057    } else { /* For o, u, x, X, p */
1058        spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
1059        if (spec->beyondMax != 0) {
1060            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
1061        }
1062    }
1063}
1064/* Compatible processing of integer negative numbers */
1065SECUREC_INLINE void SecFinishNumberNegativeInt(SecScanSpec *spec)
1066{
1067    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
1068#ifdef SECUREC_ON_64BITS
1069        if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
1070            if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) {
1071                spec->number = 0;
1072            } else {
1073                spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
1074            }
1075        }
1076#else
1077        if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
1078            if ((spec->number > SECUREC_MIN_32BITS_NEG_VALUE)) {
1079                spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
1080            } else {
1081                spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
1082            }
1083        }
1084#endif
1085        if (spec->beyondMax != 0) {
1086#ifdef SECUREC_ON_64BITS
1087            if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
1088                spec->number = 0;
1089            }
1090#else
1091            if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
1092                spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
1093            }
1094#endif
1095        }
1096    } else {            /* For o, u, x, X ,p */
1097#ifdef SECUREC_ON_64BITS
1098        if (spec->number > SECUREC_MAX_32BITS_VALUE_INC) {
1099            spec->number = SECUREC_MAX_32BITS_VALUE;
1100        } else {
1101            spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
1102        }
1103#else
1104        spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
1105#endif
1106        if (spec->beyondMax != 0) {
1107            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
1108        }
1109    }
1110}
1111
1112/* Compatible with integer positive values other than int */
1113SECUREC_INLINE void SecFinishNumberPositiveOther(SecScanSpec *spec)
1114{
1115    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
1116        if (spec->number > SECUREC_MAX_LONG_POS_VALUE) {
1117            spec->number = SECUREC_MAX_LONG_POS_VALUE;
1118        }
1119        if ((spec->beyondMax != 0 && spec->numberWidth < SECUREC_NUM_WIDTH_INT)) {
1120            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
1121        }
1122        if (spec->beyondMax != 0 && spec->numberWidth == SECUREC_NUM_WIDTH_LONG) {
1123            spec->number = SECUREC_MAX_LONG_POS_VALUE;
1124        }
1125    } else {
1126        if (spec->beyondMax != 0) {
1127            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
1128        }
1129    }
1130}
1131
1132/* Compatible processing of integer positive numbers */
1133SECUREC_INLINE void SecFinishNumberPositiveInt(SecScanSpec *spec)
1134{
1135    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
1136#ifdef SECUREC_ON_64BITS
1137        if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
1138            if (spec->number > SECUREC_MAX_64BITS_POS_VALUE) {
1139                spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
1140            }
1141        }
1142        if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
1143            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
1144        }
1145#else
1146        if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
1147            if (spec->number > SECUREC_MAX_32BITS_POS_VALUE) {
1148                spec->number = SECUREC_MAX_32BITS_POS_VALUE;
1149            }
1150        }
1151        if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
1152            spec->number = SECUREC_MAX_32BITS_POS_VALUE;
1153        }
1154#endif
1155    } else {            /* For o,u,x,X,p */
1156        if (spec->beyondMax != 0) {
1157            spec->number = SECUREC_MAX_32BITS_VALUE;
1158        }
1159    }
1160}
1161
1162#endif
1163
1164/*
1165 * Parse decimal character to integer for 64bit .
1166 */
1167static void SecDecodeNumber64Decimal(SecScanSpec *spec)
1168{
1169#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1170    if (spec->number64 > SECUREC_MAX_64BITS_VALUE_DIV_TEN) {
1171        spec->beyondMax = 1;
1172    }
1173#endif
1174    spec->number64 = SECUREC_MUL_TEN(spec->number64);
1175#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1176    if (spec->number64 == SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT) {
1177        SecUnsignedInt64 number64As = (SecUnsignedInt64)SECUREC_MAX_64BITS_VALUE - spec->number64;
1178        if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) {
1179            spec->beyondMax = 1;
1180        }
1181    }
1182#endif
1183    spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
1184}
1185
1186/*
1187 * Parse Hex character to integer for 64bit .
1188 */
1189static void SecDecodeNumber64Hex(SecScanSpec *spec)
1190{
1191#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1192    if (SECUREC_QWORD_HEX_BEYOND_MAX(spec->number64)) {
1193        spec->beyondMax = 1;
1194    }
1195#endif
1196    spec->number64 = SECUREC_MUL_SIXTEEN(spec->number64);
1197    spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(spec->ch);
1198}
1199
1200/*
1201 * Parse Octal character to integer for 64bit .
1202 */
1203static void SecDecodeNumber64Octal(SecScanSpec *spec)
1204{
1205#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1206    if (SECUREC_QWORD_OCTAL_BEYOND_MAX(spec->number64)) {
1207        spec->beyondMax = 1;
1208    }
1209#endif
1210    spec->number64 = SECUREC_MUL_EIGHT(spec->number64);
1211    spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
1212}
1213
1214#define SECUREC_DECODE_NUMBER_FUNC_NUM 2
1215
1216/*
1217 * Parse 64-bit integer formatted input, return 0 when ch is a number.
1218 */
1219SECUREC_INLINE int SecDecodeNumber(SecScanSpec *spec)
1220{
1221    /* Function name cannot add address symbol, causing 546 alarm */
1222    static void (* const secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
1223        SecDecodeNumberHex, SecDecodeNumber64Hex
1224    };
1225    static void (* const secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
1226        SecDecodeNumberOctal, SecDecodeNumber64Octal
1227    };
1228    static void (* const secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
1229        SecDecodeNumberDecimal, SecDecodeNumber64Decimal
1230    };
1231    if (spec->convChr == 'x' || spec->convChr == 'p') {
1232        if (SecIsXdigit(spec->ch) != 0) {
1233            (*secDecodeNumberHex[spec->numberArgType])(spec);
1234        } else {
1235            return -1;
1236        }
1237        return 0;
1238    }
1239    if (SecIsDigit(spec->ch) == 0) {
1240        return -1;
1241    }
1242    if (spec->convChr == 'o') {
1243        if (spec->ch < SECUREC_CHAR('8')) { /* Octal maximum limit '8' */
1244            (*secDecodeNumberOctal[spec->numberArgType])(spec);
1245        } else {
1246            return -1;
1247        }
1248    } else { /* The convChr is 'd' */
1249        (*secDecodeNumberDecimal[spec->numberArgType])(spec);
1250    }
1251    return 0;
1252}
1253
1254/*
1255 * Complete the final 32-bit integer formatted input
1256 */
1257static void SecFinishNumber(SecScanSpec *spec)
1258{
1259#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1260    if (spec->negative != 0) {
1261        if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
1262            SecFinishNumberNegativeInt(spec);
1263        } else {
1264            SecFinishNumberNegativeOther(spec);
1265        }
1266    } else {
1267        if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
1268            SecFinishNumberPositiveInt(spec);
1269        } else {
1270            SecFinishNumberPositiveOther(spec);
1271        }
1272    }
1273#else
1274    if (spec->negative != 0) {
1275#if defined(__hpux)
1276        if (spec->oriConvChr != 'p') {
1277            spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
1278        }
1279#else
1280        spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
1281#endif
1282    }
1283#endif
1284    return;
1285}
1286
1287/*
1288 * Complete the final 64-bit integer formatted input
1289 */
1290static void SecFinishNumber64(SecScanSpec *spec)
1291{
1292#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1293    if (spec->negative != 0) {
1294        if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
1295            if (spec->number64 > SECUREC_MIN_64BITS_NEG_VALUE) {
1296                spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
1297            } else {
1298                spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
1299            }
1300            if (spec->beyondMax != 0) {
1301                spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
1302            }
1303        } else {                /* For o, u, x, X, p */
1304            spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
1305            if (spec->beyondMax != 0) {
1306                spec->number64 = SECUREC_MAX_64BITS_VALUE;
1307            }
1308        }
1309    } else {
1310        if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
1311            if (spec->number64 > SECUREC_MAX_64BITS_POS_VALUE) {
1312                spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
1313            }
1314            if (spec->beyondMax != 0) {
1315                spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
1316            }
1317        } else {
1318            if (spec->beyondMax != 0) {
1319                spec->number64 = SECUREC_MAX_64BITS_VALUE;
1320            }
1321        }
1322    }
1323#else
1324    if (spec->negative != 0) {
1325#if defined(__hpux)
1326        if (spec->oriConvChr != 'p') {
1327            spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
1328        }
1329#else
1330        spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
1331#endif
1332    }
1333#endif
1334    return;
1335}
1336
1337#if SECUREC_ENABLE_SCANF_FILE
1338
1339/*
1340 *  Adjust the pointer position of the file stream
1341 */
1342SECUREC_INLINE void SecSeekStream(SecFileStream *stream)
1343{
1344    if (stream->count == 0) {
1345        if (feof(stream->pf) != 0) {
1346            /* File pointer at the end of file, don't need to seek back */
1347            stream->base[0] = '\0';
1348            return;
1349        }
1350    }
1351    /* Seek to original position, for file read, but nothing to input */
1352    if (fseek(stream->pf, stream->oriFilePos, SEEK_SET) != 0) {
1353        /* Seek failed, ignore it */
1354        stream->oriFilePos = 0;
1355        return;
1356    }
1357
1358    if (stream->fileRealRead > 0) { /* Do not seek without input data */
1359#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1360        size_t residue = stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE;
1361        size_t loops;
1362        for (loops = 0; loops < (stream->fileRealRead / SECUREC_BUFFERED_BLOK_SIZE); ++loops) {
1363            if (fread(stream->base, (size_t)SECUREC_BUFFERED_BLOK_SIZE, (size_t)1, stream->pf) != (size_t)1) {
1364                break;
1365            }
1366        }
1367        if (residue != 0) {
1368            long curFilePos;
1369            if (fread(stream->base, residue, (size_t)1, stream->pf) != (size_t)1) {
1370                return;
1371            }
1372            curFilePos = ftell(stream->pf);
1373            if (curFilePos < stream->oriFilePos ||
1374                (size_t)(unsigned long)(curFilePos - stream->oriFilePos) < stream->fileRealRead) {
1375                /* Try to remedy the problem */
1376                long adjustNum = (long)(stream->fileRealRead - (size_t)(unsigned long)(curFilePos - stream->oriFilePos));
1377                (void)fseek(stream->pf, adjustNum, SEEK_CUR);
1378            }
1379        }
1380#else
1381        /* Seek from oriFilePos. Regardless of the integer sign problem, call scanf will not read very large data */
1382        if (fseek(stream->pf, (long)stream->fileRealRead, SEEK_CUR) != 0) {
1383            /* Seek failed, ignore it */
1384            stream->oriFilePos = 0;
1385            return;
1386        }
1387#endif
1388    }
1389    return;
1390}
1391
1392/*
1393 *  Adjust the pointer position of the file stream and free memory
1394 */
1395SECUREC_INLINE void SecAdjustStream(SecFileStream *stream)
1396{
1397    if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0 && stream->base != NULL) {
1398        SecSeekStream(stream);
1399        SECUREC_FREE(stream->base);
1400        stream->base = NULL;
1401    }
1402    return;
1403}
1404#endif
1405
1406SECUREC_INLINE void SecSkipSpaceFormat(const SecUnsignedChar **format)
1407{
1408    const SecUnsignedChar *fmt = *format;
1409    while (SecIsSpace((SecInt)(int)(*fmt)) != 0) {
1410        ++fmt;
1411    }
1412    *format = fmt;
1413}
1414
1415#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)
1416/*
1417 * Handling multi-character characters
1418 */
1419SECUREC_INLINE int SecDecodeLeadByte(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream)
1420{
1421#if SECUREC_HAVE_MBTOWC
1422    const SecUnsignedChar *fmt = *format;
1423    int ch1 = (int)spec->ch;
1424    int ch2 = SecGetChar(stream, &(spec->charCount));
1425    spec->ch = (SecInt)ch2;
1426    if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch2) {
1427        /* in console mode, ungetc twice may cause problem */
1428        SecUnGetChar(ch2, stream, &(spec->charCount));
1429        SecUnGetChar(ch1, stream, &(spec->charCount));
1430        return -1;
1431    }
1432    ++fmt;
1433    if ((unsigned int)MB_CUR_MAX >= SECUREC_UTF8_BOM_HEADER_SIZE &&
1434        (((unsigned char)ch1 & SECUREC_UTF8_LEAD_1ST) == SECUREC_UTF8_LEAD_1ST) &&
1435        (((unsigned char)ch2 & SECUREC_UTF8_LEAD_2ND) == SECUREC_UTF8_LEAD_2ND)) {
1436        /* This char is very likely to be a UTF-8 char */
1437        wchar_t tempWChar;
1438        char temp[SECUREC_MULTI_BYTE_MAX_LEN];
1439        int ch3 = (int)SecGetChar(stream, &(spec->charCount));
1440        spec->ch = (SecInt)ch3;
1441        if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch3) {
1442            SecUnGetChar(ch3, stream, &(spec->charCount));
1443            return -1;
1444        }
1445        temp[0] = (char)ch1;
1446        temp[1] = (char)ch2; /* 1 index of second character */
1447        temp[2] = (char)ch3; /* 2 index of third character */
1448        temp[3] = '\0';      /* 3 of string terminator position */
1449        if (mbtowc(&tempWChar, temp, sizeof(temp)) > 0) {
1450            /* Succeed */
1451            ++fmt;
1452            --spec->charCount;
1453        } else {
1454            SecUnGetChar(ch3, stream, &(spec->charCount));
1455        }
1456    }
1457    --spec->charCount;    /* Only count as one character read */
1458    *format = fmt;
1459    return 0;
1460#else
1461    SecUnGetChar(spec->ch, stream, &(spec->charCount));
1462    (void)format; /* To clear e438 last value assigned not used , the compiler will optimize this code */
1463    return -1;
1464#endif
1465}
1466
1467SECUREC_INLINE int SecFilterWcharInFormat(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream)
1468{
1469    if (SecIsLeadByte(spec->ch) != 0) {
1470        if (SecDecodeLeadByte(spec, format, stream) != 0) {
1471            return -1;
1472        }
1473    }
1474    return 0;
1475}
1476#endif
1477
1478/*
1479 *  Resolving sequence of characters from %[ format, format wile point to ']'
1480 */
1481SECUREC_INLINE int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable)
1482{
1483    const SecUnsignedChar *fmt = *format;
1484    SecUnsignedChar prevChar = 0;
1485#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
1486    if (*fmt == SECUREC_CHAR('{')) {
1487        return -1;
1488    }
1489#endif
1490    /* For building "table" data */
1491    ++fmt; /* Skip [ */
1492    bracketTable->mask = 0; /* Set all bits to 0 */
1493    if (*fmt == SECUREC_CHAR('^')) {
1494        ++fmt;
1495        bracketTable->mask = (unsigned char)0xffU; /* Use 0xffU to set all bits to 1 */
1496    }
1497    if (*fmt == SECUREC_CHAR(']')) {
1498        prevChar = SECUREC_CHAR(']');
1499        ++fmt;
1500        SecBracketSetBit(bracketTable->table, SECUREC_CHAR(']'));
1501    }
1502    while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
1503        SecUnsignedChar expCh = *fmt;
1504        ++fmt;
1505        if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) {
1506            /* Normal character */
1507            prevChar = expCh;
1508            SecBracketSetBit(bracketTable->table, expCh);
1509        } else {
1510            /* For %[a-z] */
1511            expCh = *fmt;   /* Get end of range */
1512            ++fmt;
1513            if (prevChar <= expCh) {  /* %[a-z] %[a-a] */
1514                SecBracketSetBitRange(bracketTable->table, prevChar, expCh);
1515            } else {
1516                /* For %[z-a] */
1517#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1518                /* Swap start and end characters */
1519                SecBracketSetBitRange(bracketTable->table, expCh, prevChar);
1520#else
1521                SecBracketSetBit(bracketTable->table, SECUREC_CHAR('-'));
1522                SecBracketSetBit(bracketTable->table, expCh);
1523#endif
1524            }
1525            prevChar = 0;
1526        }
1527    }
1528    *format = fmt;
1529    return 0;
1530}
1531
1532#ifdef SECUREC_FOR_WCHAR
1533SECUREC_INLINE int SecInputForWchar(SecScanSpec *spec)
1534{
1535    void *endPtr = spec->argPtr;
1536    if (spec->isWCharOrLong > 0) {
1537        *(wchar_t UNALIGNED *)endPtr = (wchar_t)spec->ch;
1538        endPtr = (wchar_t *)endPtr + 1;
1539        --spec->arrayWidth;
1540    } else {
1541#if SECUREC_HAVE_WCTOMB
1542        int temp;
1543        char tmpBuf[SECUREC_MB_LEN + 1];
1544        SECUREC_MASK_MSVC_CRT_WARNING temp = wctomb(tmpBuf, (wchar_t)spec->ch);
1545        SECUREC_END_MASK_MSVC_CRT_WARNING
1546        if (temp <= 0 || (size_t)(unsigned int)temp > sizeof(tmpBuf)) {
1547            /* If wctomb  error, then ignore character */
1548            return 0;
1549        }
1550        if (((size_t)(unsigned int)temp) > spec->arrayWidth) {
1551            return -1;
1552        }
1553        if (memcpy_s(endPtr, spec->arrayWidth, tmpBuf, (size_t)(unsigned int)temp) != EOK) {
1554            return -1;
1555        }
1556        endPtr = (char *)endPtr + temp;
1557        spec->arrayWidth -= (size_t)(unsigned int)temp;
1558#else
1559        return -1;
1560#endif
1561    }
1562    spec->argPtr = endPtr;
1563    return 0;
1564}
1565#endif
1566
1567#ifndef SECUREC_FOR_WCHAR
1568#if SECUREC_HAVE_WCHART
1569SECUREC_INLINE wchar_t SecConvertInputCharToWchar(SecScanSpec *spec, SecFileStream *stream)
1570{
1571    wchar_t tempWChar = L'?';   /* Set default char is ? */
1572#if SECUREC_HAVE_MBTOWC
1573    char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1];
1574    temp[0] = (char)spec->ch;
1575    temp[1] = '\0';
1576#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1577    if (SecIsLeadByte(spec->ch) != 0) {
1578        spec->ch = SecGetChar(stream, &(spec->charCount));
1579        temp[1] = (char)spec->ch;
1580        temp[2] = '\0'; /* 2 of string terminator position */
1581    }
1582    if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) {
1583        /* No string termination error for tool */
1584        tempWChar = L'?';
1585    }
1586#else
1587    if (SecIsLeadByte(spec->ch) != 0) {
1588        int convRes = 0;
1589        int di = 1;
1590        /* On Linux like system, the string is encoded in UTF-8 */
1591        while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) {
1592            spec->ch = SecGetChar(stream, &(spec->charCount));
1593            temp[di] = (char)spec->ch;
1594            ++di;
1595            temp[di] = '\0';
1596            convRes = mbtowc(&tempWChar, temp, sizeof(temp));
1597        }
1598        if (convRes <= 0) {
1599            tempWChar = L'?';
1600        }
1601    } else {
1602        if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) {
1603            tempWChar = L'?';
1604        }
1605    }
1606#endif
1607#else
1608    (void)spec;      /* To clear e438 last value assigned not used , the compiler will optimize this code */
1609    (void)stream;    /* To clear e438 last value assigned not used , the compiler will optimize this code */
1610#endif /* SECUREC_HAVE_MBTOWC */
1611
1612    return tempWChar;
1613}
1614#endif /* SECUREC_HAVE_WCHART */
1615
1616SECUREC_INLINE int SecInputForChar(SecScanSpec *spec, SecFileStream *stream)
1617{
1618    void *endPtr = spec->argPtr;
1619    if (spec->isWCharOrLong > 0) {
1620#if SECUREC_HAVE_WCHART
1621        *(wchar_t UNALIGNED *)endPtr = SecConvertInputCharToWchar(spec, stream);
1622        endPtr = (wchar_t *)endPtr + 1;
1623        --spec->arrayWidth;
1624#else
1625    (void)stream;    /* To clear e438 last value assigned not used , the compiler will optimize this code */
1626    return -1;
1627#endif
1628    } else {
1629        *(char *)endPtr = (char)spec->ch;
1630        endPtr = (char *)endPtr + 1;
1631        --spec->arrayWidth;
1632    }
1633    spec->argPtr = endPtr;
1634    return 0;
1635}
1636#endif
1637
1638/*
1639 * Scan digital part of %d %i %o %u %x %p.
1640 * Return 0 OK
1641 */
1642SECUREC_INLINE int SecInputNumberDigital(SecFileStream *stream, SecScanSpec *spec)
1643{
1644    static void (* const secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
1645        SecFinishNumber, SecFinishNumber64
1646    };
1647    while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
1648        spec->ch = SecGetChar(stream, &(spec->charCount));
1649        /* Decode ch to number */
1650        if (SecDecodeNumber(spec) != 0) {
1651            SecUnGetChar(spec->ch, stream, &(spec->charCount));
1652            break;
1653        }
1654        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
1655        spec->numberState = SECUREC_NUMBER_STATE_STARTED;
1656    }
1657    /* Handling integer negative numbers and beyond max */
1658    (*secFinishNumber[spec->numberArgType])(spec);
1659    if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) {
1660        return 0;
1661    }
1662    return -1;
1663}
1664
1665/*
1666 * Scan %d %i %o %u %x %p.
1667 * Return 0 OK
1668 */
1669SECUREC_INLINE int SecInputNumber(SecFileStream *stream, SecScanSpec *spec)
1670{
1671    /* Character already read */
1672    if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
1673        if (spec->ch == SECUREC_CHAR('-')) {
1674            spec->negative = 1;
1675#if SECUREC_IN_KERNEL
1676            /* In kernel Refuse to enter negative number */
1677            if (SECUREC_CONVERT_IS_UNSIGNED(spec->oriConvChr)) {
1678                return -1;
1679            }
1680#endif
1681        }
1682        SECUREC_FILED_WIDTH_DEC(spec); /* Do not need to check width here, must be greater than 0 */
1683        spec->ch = SecGetChar(stream, &(spec->charCount)); /* Eat + or - */
1684        spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next character, used for the '0' judgments */
1685        SecUnGetChar(spec->ch, stream, &(spec->charCount)); /* Not sure if it was actually read, so push back */
1686    }
1687
1688    if (spec->oriConvChr == 'i') {
1689        spec->convChr = 'd'; /* The i could be d, o, or x, use d as default */
1690    }
1691
1692    if (spec->ch == SECUREC_CHAR('0') && (spec->oriConvChr == 'x' || spec->oriConvChr == 'i') &&
1693        SECUREC_FILED_WIDTH_ENOUGH(spec)) {
1694        /* Input string begin with 0, may be 0x123  0X123  0123  0x  01  0yy  09  0  0ab 00 */
1695        SECUREC_FILED_WIDTH_DEC(spec);
1696        spec->ch = SecGetChar(stream, &(spec->charCount)); /* ch is '0' */
1697
1698        /* Read only '0' due to width limitation */
1699        if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) {
1700            /* The number or number64 in spec has been set 0 */
1701            return 0;
1702        }
1703
1704        spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next char to check x or X, do not dec width */
1705        if ((SecChar)spec->ch == SECUREC_CHAR('x') || (SecChar)spec->ch == SECUREC_CHAR('X')) {
1706            spec->convChr = 'x';
1707            SECUREC_FILED_WIDTH_DEC(spec); /* Make incorrect width for x or X */
1708        } else {
1709            if (spec->oriConvChr == 'i') {
1710                spec->convChr = 'o';
1711            }
1712            /* For "0y" "08" "01" "0a" ... ,push the 'y' '8' '1' 'a'  back */
1713            SecUnGetChar(spec->ch, stream, &(spec->charCount));
1714            /* Since 0 has been read, it indicates that a valid character has been read */
1715            spec->numberState = SECUREC_NUMBER_STATE_STARTED;
1716        }
1717    }
1718    return SecInputNumberDigital(stream, spec);
1719}
1720
1721/*
1722 * Scan %c %s %[
1723 * Return 0 OK
1724 */
1725SECUREC_INLINE int SecInputString(SecFileStream *stream, SecScanSpec *spec,
1726    const SecBracketTable *bracketTable, int *doneCount)
1727{
1728    void *startPtr = spec->argPtr;
1729    int suppressed = 0;
1730    int errNoMem = 0;
1731
1732    while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
1733        SECUREC_FILED_WIDTH_DEC(spec);
1734        spec->ch = SecGetChar(stream, &(spec->charCount));
1735        /*
1736         * The char condition or string condition and bracket condition.
1737         * Only supports wide characters with a maximum length of two bytes
1738         */
1739        if (spec->ch != SECUREC_EOF && (SecCanInputCharacter(spec->convChr) != 0 ||
1740            SecCanInputString(spec->convChr, spec->ch) != 0 ||
1741            SecCanInputForBracket(spec->convChr, spec->ch, bracketTable) != 0)) {
1742            if (spec->suppress != 0) {
1743                /* Used to identify processed data for %*, use argPtr to identify will cause 613, so use suppressed */
1744                suppressed = 1;
1745                continue;
1746            }
1747            /* Now suppress is not set */
1748            if (spec->arrayWidth == 0) {
1749                errNoMem = 1; /* We have exhausted the user's buffer */
1750                break;
1751            }
1752#ifdef SECUREC_FOR_WCHAR
1753            errNoMem = SecInputForWchar(spec);
1754#else
1755            errNoMem = SecInputForChar(spec, stream);
1756#endif
1757            if (errNoMem != 0) {
1758                break;
1759            }
1760        } else {
1761            SecUnGetChar(spec->ch, stream, &(spec->charCount));
1762            break;
1763        }
1764    }
1765
1766    if (errNoMem != 0) {
1767        /* In case of error, blank out the input buffer */
1768        SecAddEndingZero(startPtr, spec);
1769        return -1;
1770    }
1771    if ((spec->suppress != 0 && suppressed == 0) ||
1772        (spec->suppress == 0 && startPtr == spec->argPtr)) {
1773        /* No input was scanned */
1774        return -1;
1775    }
1776    if (spec->convChr != 'c') {
1777        /* Add null-terminate for strings */
1778        SecAddEndingZero(spec->argPtr, spec);
1779    }
1780    if (spec->suppress == 0) {
1781        *doneCount = *doneCount + 1;
1782    }
1783    return 0;
1784}
1785
1786#ifdef SECUREC_FOR_WCHAR
1787/*
1788 * Allocate buffer for wchar version of %[.
1789 * Return 0 OK
1790 */
1791SECUREC_INLINE int SecAllocBracketTable(SecBracketTable *bracketTable)
1792{
1793    if (bracketTable->table == NULL) {
1794        /* Table should be freed after use */
1795        bracketTable->table = (unsigned char *)SECUREC_MALLOC(SECUREC_BRACKET_TABLE_SIZE);
1796        if (bracketTable->table == NULL) {
1797            return -1;
1798        }
1799    }
1800    return 0;
1801}
1802
1803/*
1804 * Free buffer for wchar version of %[
1805 */
1806SECUREC_INLINE void SecFreeBracketTable(SecBracketTable *bracketTable)
1807{
1808    if (bracketTable->table != NULL) {
1809        SECUREC_FREE(bracketTable->table);
1810        bracketTable->table = NULL;
1811    }
1812}
1813#endif
1814
1815#ifdef SECUREC_FOR_WCHAR
1816/*
1817 *  Formatting input core functions for wchar version.Called by a function such as vswscanf_s
1818 */
1819int SecInputSW(SecFileStream *stream, const wchar_t *cFormat, va_list argList)
1820#else
1821/*
1822 * Formatting input core functions for char version.Called by a function such as vsscanf_s
1823 */
1824int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList)
1825#endif
1826{
1827    const SecUnsignedChar *format = (const SecUnsignedChar *)cFormat;
1828    SecBracketTable bracketTable = SECUREC_INIT_BRACKET_TABLE;
1829    SecScanSpec spec;
1830    int doneCount = 0;
1831    int formatError = 0;
1832    int paraIsNull = 0;
1833    int match = 0; /* When % is found , inc this value */
1834    int errRet = 0;
1835#if SECUREC_ENABLE_SCANF_FLOAT
1836    SecFloatSpec floatSpec;
1837    SecInitFloatSpec(&floatSpec);
1838#endif
1839    spec.ch = 0; /* Need to initialize to 0 */
1840    spec.charCount = 0; /* Need to initialize to 0 */
1841
1842    /* Format must not NULL, use err < 1 to clear 845 */
1843    while (errRet < 1 && *format != SECUREC_CHAR('\0')) {
1844        /* Skip space in format and space in input */
1845        if (SecIsSpace((SecInt)(int)(*format)) != 0) {
1846            /* Read first no space char */
1847            spec.ch = SecSkipSpaceChar(stream, &(spec.charCount));
1848            /* Read the EOF cannot be returned directly here, because the case of " %n" needs to be handled */
1849            /* Put fist no space char backup. put EOF back is also OK, and to modify the character count */
1850            SecUnGetChar(spec.ch, stream, &(spec.charCount));
1851            SecSkipSpaceFormat(&format);
1852            continue;
1853        }
1854
1855        if (*format != SECUREC_CHAR('%')) {
1856            spec.ch = SecGetChar(stream, &(spec.charCount));
1857            if ((int)(*format) != (int)(spec.ch)) {
1858                SecUnGetChar(spec.ch, stream, &(spec.charCount));
1859                break;
1860            }
1861            ++format;
1862#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)
1863            if (SecFilterWcharInFormat(&spec, &format, stream) != 0) {
1864                break;
1865            }
1866#endif
1867            continue;
1868        }
1869
1870        /* Now *format is % */
1871        /* Set default value for each % */
1872        SecSetDefaultScanSpec(&spec);
1873        if (SecDecodeScanFlag(&format, &spec) != 0) {
1874            formatError = 1;
1875            ++errRet;
1876            continue;
1877        }
1878        if (!SECUREC_FILED_WIDTH_ENOUGH(&spec)) {
1879            /* 0 width in format */
1880            ++errRet;
1881            continue;
1882        }
1883
1884        /* Update wchar flag for %S %C */
1885        SecUpdateWcharFlagByType(*format, &spec);
1886
1887        spec.convChr = SECUREC_TO_LOWERCASE(*format);
1888        spec.oriConvChr = spec.convChr; /* convChr may be modified to handle integer logic */
1889        if (spec.convChr != 'n') {
1890            if (spec.convChr != 'c' && spec.convChr != SECUREC_BRACE) {
1891                spec.ch = SecSkipSpaceChar(stream, &(spec.charCount));
1892            } else {
1893                spec.ch = SecGetChar(stream, &(spec.charCount));
1894            }
1895            if (spec.ch == SECUREC_EOF) {
1896                ++errRet;
1897                continue;
1898            }
1899        }
1900
1901        /* Now no 0 width in format and get one char from input */
1902        switch (spec.oriConvChr) {
1903            case 'c': /* Also 'C' */
1904                if (spec.widthSet == 0) {
1905                    spec.widthSet = 1;
1906                    spec.width = 1;
1907                }
1908                /* fall-through */ /* FALLTHRU */
1909            case 's': /* Also 'S': */
1910                /* fall-through */ /* FALLTHRU */
1911            case SECUREC_BRACE:
1912                /* Unset last char to stream */
1913                SecUnGetChar(spec.ch, stream, &(spec.charCount));
1914                /* Check dest buffer and size */
1915                if (spec.suppress == 0) {
1916                    spec.argPtr = (void *)va_arg(argList, void *);
1917                    if (spec.argPtr == NULL) {
1918                        paraIsNull = 1;
1919                        ++errRet;
1920                        continue;
1921                    }
1922                    /* Get the next argument, size of the array in characters */
1923                    spec.arrayWidth = SECUREC_GET_ARRAYWIDTH(argList);
1924                    if (SECUREC_ARRAY_WIDTH_IS_WRONG(spec)) {
1925                        /* Do not clear buffer just go error */
1926                        ++errRet;
1927                        continue;
1928                    }
1929                    /* One element is needed for '\0' for %s and %[ */
1930                    if (spec.convChr != 'c') {
1931                        --spec.arrayWidth;
1932                    }
1933                } else {
1934                    /* Set argPtr to  NULL  is necessary, in suppress mode we don't use argPtr to store data */
1935                    spec.argPtr = NULL;
1936                }
1937
1938                if (spec.convChr == SECUREC_BRACE) {
1939                    /* Malloc when first %[ is meet  for wchar version */
1940#ifdef SECUREC_FOR_WCHAR
1941                    if (SecAllocBracketTable(&bracketTable) != 0) {
1942                        ++errRet;
1943                        continue;
1944                    }
1945#endif
1946                    (void)SECUREC_MEMSET_FUNC_OPT(bracketTable.table, 0, (size_t)SECUREC_BRACKET_TABLE_SIZE);
1947                    if (SecSetupBracketTable(&format, &bracketTable) != 0) {
1948                        ++errRet;
1949                        continue;
1950                    }
1951
1952                    if (*format == SECUREC_CHAR('\0')) {
1953                        /* Default add string terminator */
1954                        SecAddEndingZero(spec.argPtr, &spec);
1955                        ++errRet;
1956                        /* Truncated format */
1957                        continue;
1958                    }
1959                }
1960
1961                /* Set completed.  Now read string or character */
1962                if (SecInputString(stream, &spec, &bracketTable, &doneCount) != 0) {
1963                    ++errRet;
1964                    continue;
1965                }
1966                break;
1967            case 'p':
1968                /* Make %hp same as %p */
1969                spec.numberWidth = SECUREC_NUM_WIDTH_INT;
1970#ifdef SECUREC_ON_64BITS
1971                spec.numberArgType = 1;
1972#endif
1973                /* fall-through */ /* FALLTHRU */
1974            case 'o': /* fall-through */ /* FALLTHRU */
1975            case 'u': /* fall-through */ /* FALLTHRU */
1976            case 'd': /* fall-through */ /* FALLTHRU */
1977            case 'i': /* fall-through */ /* FALLTHRU */
1978            case 'x':
1979                /* Unset last char to stream */
1980                SecUnGetChar(spec.ch, stream, &(spec.charCount));
1981                if (SecInputNumber(stream, &spec) != 0) {
1982                    ++errRet;
1983                    continue;
1984                }
1985                if (spec.suppress == 0) {
1986                    spec.argPtr = (void *)va_arg(argList, void *);
1987                    if (spec.argPtr == NULL) {
1988                        paraIsNull = 1;
1989                        ++errRet;
1990                        continue;
1991                    }
1992                    SecAssignNumber(&spec);
1993                    ++doneCount;
1994                }
1995                break;
1996            case 'n': /* Char count */
1997                if (spec.suppress == 0) {
1998                    spec.argPtr = (void *)va_arg(argList, void *);
1999                    if (spec.argPtr == NULL) {
2000                        paraIsNull = 1;
2001                        ++errRet;
2002                        continue;
2003                    }
2004                    spec.number = (unsigned long)(unsigned int)(spec.charCount);
2005                    spec.numberArgType = 0;
2006                    SecAssignNumber(&spec);
2007                }
2008                break;
2009            case 'e': /* fall-through */ /* FALLTHRU */
2010            case 'f': /* fall-through */ /* FALLTHRU */
2011            case 'g': /* Scan a float */
2012                /* Unset last char to stream */
2013                SecUnGetChar(spec.ch, stream, &(spec.charCount));
2014#if SECUREC_ENABLE_SCANF_FLOAT
2015                if (SecInputFloat(stream, &spec, &floatSpec) != 0) {
2016                    ++errRet;
2017                    continue;
2018                }
2019                if (spec.suppress == 0) {
2020                    spec.argPtr = (void *)va_arg(argList, void *);
2021                    if (spec.argPtr == NULL) {
2022                        ++errRet;
2023                        paraIsNull = 1;
2024                        continue;
2025                    }
2026                    if (SecAssignFloat(&floatSpec, &spec) != 0) {
2027                        ++errRet;
2028                        continue;
2029                    }
2030                    ++doneCount;
2031                }
2032                break;
2033#else /* SECUREC_ENABLE_SCANF_FLOAT */
2034                ++errRet;
2035                continue;
2036#endif
2037            default:
2038                if ((int)(*format) != (int)spec.ch) {
2039                    SecUnGetChar(spec.ch, stream, &(spec.charCount));
2040                    formatError = 1;
2041                    ++errRet;
2042                    continue;
2043                } else {
2044                    --match; /* Compensate for the self-increment of the following code */
2045                }
2046                break;
2047        }
2048        ++match;
2049        ++format;
2050    }
2051
2052#ifdef SECUREC_FOR_WCHAR
2053    SecFreeBracketTable(&bracketTable);
2054#endif
2055
2056#if SECUREC_ENABLE_SCANF_FLOAT
2057    SecFreeFloatSpec(&floatSpec, &doneCount);
2058#endif
2059
2060#if SECUREC_ENABLE_SCANF_FILE
2061    SecAdjustStream(stream);
2062#endif
2063
2064    if (spec.ch == SECUREC_EOF) {
2065        return ((doneCount != 0 || match != 0) ? doneCount : SECUREC_SCANF_EINVAL);
2066    }
2067    if (formatError != 0 || paraIsNull != 0) {
2068        /* Invalid Input Format or parameter, but not meet EOF */
2069        return SECUREC_SCANF_ERROR_PARA;
2070    }
2071    return doneCount;
2072}
2073
2074#if SECUREC_ENABLE_SCANF_FILE
2075/*
2076 *  Get char from stream use std function
2077 */
2078SECUREC_INLINE SecInt SecGetCharFromStream(const SecFileStream *stream)
2079{
2080    SecInt ch;
2081    ch = SECUREC_GETC(stream->pf);
2082    return ch;
2083}
2084
2085/*
2086 * Try to read the BOM header, when meet a BOM head, discard it, then data is Aligned to base
2087 */
2088SECUREC_INLINE void SecReadAndSkipBomHeader(SecFileStream *stream)
2089{
2090    /* Use size_t type conversion  to clean e747 */
2091    stream->count = fread(stream->base, (size_t)1, (size_t)SECUREC_BOM_HEADER_SIZE, stream->pf);
2092    if (stream->count > SECUREC_BOM_HEADER_SIZE) {
2093        stream->count = 0;
2094    }
2095    if (SECUREC_BEGIN_WITH_BOM(stream->base, stream->count)) {
2096        /* It's BOM header, discard it */
2097        stream->count = 0;
2098    }
2099}
2100
2101/*
2102 *  Get char  from file stream or buffer
2103 */
2104SECUREC_INLINE SecInt SecGetCharFromFile(SecFileStream *stream)
2105{
2106    SecInt ch;
2107    if (stream->count < sizeof(SecChar)) {
2108        /* Load file to buffer */
2109        size_t len;
2110        if (stream->base != NULL) {
2111            /* Put the last unread data in the buffer head */
2112            for (len = 0; len < stream->count; ++len) {
2113                stream->base[len] = stream->cur[len];
2114            }
2115        } else {
2116            stream->oriFilePos = ftell(stream->pf);   /* Save original file read position */
2117            if (stream->oriFilePos == -1) {
2118                /* It may be a pipe stream */
2119                stream->flag = SECUREC_PIPE_STREAM_FLAG;
2120                return SecGetCharFromStream(stream);
2121            }
2122            /* Reserve the length of BOM head */
2123            stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE +
2124                SECUREC_BOM_HEADER_SIZE + sizeof(SecChar)); /* To store '\0' and aligned to wide char */
2125            if (stream->base == NULL) {
2126                return SECUREC_EOF;
2127            }
2128            /* First read file */
2129            if (stream->oriFilePos == 0) {
2130                /* Make sure the data is aligned to base */
2131                SecReadAndSkipBomHeader(stream);
2132            }
2133        }
2134
2135        /* Skip existing data and read data */
2136        len = fread(stream->base + stream->count, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf);
2137        if (len > SECUREC_BUFFERED_BLOK_SIZE) { /* It won't happen, */
2138            len = 0;
2139        }
2140        stream->count += len;
2141        stream->cur = stream->base;
2142        stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG;
2143        stream->base[stream->count] = '\0';   /* For tool Warning string null */
2144    }
2145
2146    SECUREC_GET_CHAR(stream, &ch);
2147    if (ch != SECUREC_EOF) {
2148        stream->fileRealRead += sizeof(SecChar);
2149    }
2150    return ch;
2151}
2152#endif
2153
2154/*
2155 *  Get char  for wchar version
2156 */
2157SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter)
2158{
2159    *counter = *counter + 1; /* Always plus 1 */
2160    /* The main scenario is scanf str */
2161    if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) {
2162        SecInt ch;
2163        SECUREC_GET_CHAR(stream, &ch);
2164        return ch;
2165    }
2166#if SECUREC_ENABLE_SCANF_FILE
2167    if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0) {
2168        return SecGetCharFromFile(stream);
2169    }
2170    if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) {
2171        return SecGetCharFromStream(stream);
2172    }
2173#endif
2174    return SECUREC_EOF;
2175}
2176
2177/*
2178 *  Unget Public realization char for wchar and char version
2179 */
2180SECUREC_INLINE void SecUnGetCharImpl(SecInt ch, SecFileStream *stream)
2181{
2182    if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) {
2183        SECUREC_UN_GET_CHAR(stream);
2184        return;
2185    }
2186#if SECUREC_ENABLE_SCANF_FILE
2187    if ((stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) != 0) {
2188        SECUREC_UN_GET_CHAR(stream);
2189        if (stream->fileRealRead > 0) {
2190            stream->fileRealRead -= sizeof(SecChar);
2191        }
2192        return;
2193    }
2194    if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) {
2195        (void)SECUREC_UN_GETC(ch, stream->pf);
2196        return;
2197    }
2198#else
2199    (void)ch; /* To clear e438 last value assigned not used , the compiler will optimize this code */
2200#endif
2201}
2202
2203/*
2204 *  Unget char  for char version
2205 */
2206SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter)
2207{
2208    *counter = *counter - 1; /* Always minus 1 */
2209    if (ch != SECUREC_EOF) {
2210        SecUnGetCharImpl(ch, stream);
2211    }
2212}
2213
2214/*
2215 *  Skip space char by isspace
2216 */
2217SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter)
2218{
2219    SecInt ch;
2220    do {
2221        ch = SecGetChar(stream, counter);
2222        if (ch == SECUREC_EOF) {
2223            break;
2224        }
2225    } while (SecIsSpace(ch) != 0);
2226    return ch;
2227}
2228#endif /* INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 */
2229
2230