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