13d58139fSopenharmony_ci/*
23d58139fSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved.
33d58139fSopenharmony_ci * Licensed under Mulan PSL v2.
43d58139fSopenharmony_ci * You can use this software according to the terms and conditions of the Mulan PSL v2.
53d58139fSopenharmony_ci * You may obtain a copy of Mulan PSL v2 at:
63d58139fSopenharmony_ci *          http://license.coscl.org.cn/MulanPSL2
73d58139fSopenharmony_ci * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
83d58139fSopenharmony_ci * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
93d58139fSopenharmony_ci * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
103d58139fSopenharmony_ci * See the Mulan PSL v2 for more details.
113d58139fSopenharmony_ci * Description: Used by secureinput_a.c and secureinput_w.c to include.
123d58139fSopenharmony_ci *              This file provides a template function for ANSI and UNICODE compiling by
133d58139fSopenharmony_ci *              different type definition. The functions of SecInputS or
143d58139fSopenharmony_ci *              SecInputSW provides internal implementation for scanf family API, such as sscanf_s, fscanf_s.
153d58139fSopenharmony_ci * Create: 2014-02-25
163d58139fSopenharmony_ci * Notes: The formatted input processing results of integers on different platforms are different.
173d58139fSopenharmony_ci */
183d58139fSopenharmony_ci/*
193d58139fSopenharmony_ci * [Standardize-exceptions] Use unsafe function: Performance-sensitive
203d58139fSopenharmony_ci * [reason] Always used in the performance critical path,
213d58139fSopenharmony_ci *          and sufficient input validation is performed before calling
223d58139fSopenharmony_ci */
233d58139fSopenharmony_ci#ifndef INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
243d58139fSopenharmony_ci#define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
253d58139fSopenharmony_ci
263d58139fSopenharmony_ci#if SECUREC_IN_KERNEL
273d58139fSopenharmony_ci#if !defined(SECUREC_CTYPE_MACRO_ADAPT)
283d58139fSopenharmony_ci#include <linux/ctype.h>
293d58139fSopenharmony_ci#endif
303d58139fSopenharmony_ci#else
313d58139fSopenharmony_ci#if !defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT)
323d58139fSopenharmony_ci#include <ctype.h>
333d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
343d58139fSopenharmony_ci#include <wctype.h>             /* For iswspace */
353d58139fSopenharmony_ci#endif
363d58139fSopenharmony_ci#endif
373d58139fSopenharmony_ci#endif
383d58139fSopenharmony_ci
393d58139fSopenharmony_ci#ifndef EOF
403d58139fSopenharmony_ci#define EOF  (-1)
413d58139fSopenharmony_ci#endif
423d58139fSopenharmony_ci
433d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_SHORT                 0
443d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_INT                   1
453d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_LONG                  2
463d58139fSopenharmony_ci#define SECUREC_NUM_WIDTH_LONG_LONG             3 /* Also long double */
473d58139fSopenharmony_ci
483d58139fSopenharmony_ci#define SECUREC_BUFFERED_BLOK_SIZE              1024U
493d58139fSopenharmony_ci
503d58139fSopenharmony_ci#if defined(SECUREC_VXWORKS_PLATFORM) && !defined(va_copy) && !defined(__va_copy)
513d58139fSopenharmony_ci/* The name is the same as system macro. */
523d58139fSopenharmony_ci#define __va_copy(dest, src) do { \
533d58139fSopenharmony_ci    size_t destSize_ = (size_t)sizeof(dest); \
543d58139fSopenharmony_ci    size_t srcSize_ = (size_t)sizeof(src); \
553d58139fSopenharmony_ci    if (destSize_ != srcSize_) { \
563d58139fSopenharmony_ci        SECUREC_MEMCPY_WARP_OPT((dest), (src), sizeof(va_list)); \
573d58139fSopenharmony_ci    } else { \
583d58139fSopenharmony_ci        SECUREC_MEMCPY_WARP_OPT(&(dest), &(src), sizeof(va_list)); \
593d58139fSopenharmony_ci    } \
603d58139fSopenharmony_ci} SECUREC_WHILE_ZERO
613d58139fSopenharmony_ci#endif
623d58139fSopenharmony_ci
633d58139fSopenharmony_ci#define SECUREC_MULTI_BYTE_MAX_LEN              6
643d58139fSopenharmony_ci
653d58139fSopenharmony_ci/* Compatibility macro name cannot be modifie */
663d58139fSopenharmony_ci#ifndef UNALIGNED
673d58139fSopenharmony_ci#if !(defined(_M_IA64)) && !(defined(_M_AMD64))
683d58139fSopenharmony_ci#define UNALIGNED
693d58139fSopenharmony_ci#else
703d58139fSopenharmony_ci#define UNALIGNED __unaligned
713d58139fSopenharmony_ci#endif
723d58139fSopenharmony_ci#endif
733d58139fSopenharmony_ci
743d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
753d58139fSopenharmony_ci/* Max 64bit value is 0xffffffffffffffff */
763d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_VALUE                18446744073709551615ULL
773d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_VALUE_DIV_TEN        1844674407370955161ULL
783d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT 18446744073709551610ULL
793d58139fSopenharmony_ci#define SECUREC_MIN_64BITS_NEG_VALUE            9223372036854775808ULL
803d58139fSopenharmony_ci#define SECUREC_MAX_64BITS_POS_VALUE            9223372036854775807ULL
813d58139fSopenharmony_ci#define SECUREC_MIN_32BITS_NEG_VALUE            2147483648UL
823d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_POS_VALUE            2147483647UL
833d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_VALUE                4294967295UL
843d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_VALUE_INC            4294967296UL
853d58139fSopenharmony_ci#define SECUREC_MAX_32BITS_VALUE_DIV_TEN        429496729UL
863d58139fSopenharmony_ci#define SECUREC_LONG_BIT_NUM                    ((unsigned int)(sizeof(long) << 3U))
873d58139fSopenharmony_ci/* Use ULL to clean up cl6x compilation alerts */
883d58139fSopenharmony_ci#define SECUREC_MAX_LONG_POS_VALUE              ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)) - 1)
893d58139fSopenharmony_ci#define SECUREC_MIN_LONG_NEG_VALUE              ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)))
903d58139fSopenharmony_ci
913d58139fSopenharmony_ci/* Covert to long long to clean up cl6x compilation alerts */
923d58139fSopenharmony_ci#define SECUREC_LONG_HEX_BEYOND_MAX(number)     (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0)
933d58139fSopenharmony_ci#define SECUREC_LONG_OCTAL_BEYOND_MAX(number)   (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 3U)) > 0)
943d58139fSopenharmony_ci
953d58139fSopenharmony_ci#define SECUREC_QWORD_HEX_BEYOND_MAX(number)    (((number) >> (64U - 4U)) > 0)
963d58139fSopenharmony_ci#define SECUREC_QWORD_OCTAL_BEYOND_MAX(number)  (((number) >> (64U - 3U)) > 0)
973d58139fSopenharmony_ci
983d58139fSopenharmony_ci#define SECUREC_LP64_BIT_WIDTH                  64
993d58139fSopenharmony_ci#define SECUREC_LP32_BIT_WIDTH                  32
1003d58139fSopenharmony_ci
1013d58139fSopenharmony_ci#define SECUREC_CONVERT_IS_SIGNED(conv) ((conv) == 'd' || (conv) == 'i')
1023d58139fSopenharmony_ci#endif
1033d58139fSopenharmony_ci
1043d58139fSopenharmony_ci#define SECUREC_BRACE                           '{'     /* [ to { */
1053d58139fSopenharmony_ci#define SECUREC_FILED_WIDTH_ENOUGH(spec) ((spec)->widthSet == 0 || (spec)->width > 0)
1063d58139fSopenharmony_ci#define SECUREC_FILED_WIDTH_DEC(spec) do { \
1073d58139fSopenharmony_ci    if ((spec)->widthSet != 0) { \
1083d58139fSopenharmony_ci        --(spec)->width; \
1093d58139fSopenharmony_ci    } \
1103d58139fSopenharmony_ci} SECUREC_WHILE_ZERO
1113d58139fSopenharmony_ci
1123d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
1133d58139fSopenharmony_ci/* Bits for all wchar, size is 65536/8, only supports wide characters with a maximum length of two bytes */
1143d58139fSopenharmony_ci#define SECUREC_BRACKET_TABLE_SIZE    8192
1153d58139fSopenharmony_ci#define SECUREC_EOF WEOF
1163d58139fSopenharmony_ci#define SECUREC_MB_LEN 16       /* Max. # bytes in multibyte char  ,see MB_LEN_MAX */
1173d58139fSopenharmony_ci#else
1183d58139fSopenharmony_ci/* Bits for all char, size is 256/8 */
1193d58139fSopenharmony_ci#define SECUREC_BRACKET_TABLE_SIZE    32
1203d58139fSopenharmony_ci#define SECUREC_EOF EOF
1213d58139fSopenharmony_ci#endif
1223d58139fSopenharmony_ci
1233d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART
1243d58139fSopenharmony_ci#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \
1253d58139fSopenharmony_ci    ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN) || \
1263d58139fSopenharmony_ci    ((spec).isWCharOrLong > 0 && (spec).arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN))
1273d58139fSopenharmony_ci#else
1283d58139fSopenharmony_ci#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || (spec).arrayWidth > SECUREC_STRING_MAX_LEN)
1293d58139fSopenharmony_ci#endif
1303d58139fSopenharmony_ci
1313d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
1323d58139fSopenharmony_ci/* Use 0xffffffffUL mask to pass integer as array length */
1333d58139fSopenharmony_ci#define SECUREC_GET_ARRAYWIDTH(argList) (((size_t)va_arg((argList), size_t)) & 0xffffffffUL)
1343d58139fSopenharmony_ci#else /* !SECUREC_ON_64BITS */
1353d58139fSopenharmony_ci#define SECUREC_GET_ARRAYWIDTH(argList) ((size_t)va_arg((argList), size_t))
1363d58139fSopenharmony_ci#endif
1373d58139fSopenharmony_ci
1383d58139fSopenharmony_citypedef struct {
1393d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
1403d58139fSopenharmony_ci    unsigned char *table; /* Default NULL */
1413d58139fSopenharmony_ci#else
1423d58139fSopenharmony_ci    unsigned char table[SECUREC_BRACKET_TABLE_SIZE]; /* Array length is large enough in application scenarios */
1433d58139fSopenharmony_ci#endif
1443d58139fSopenharmony_ci    unsigned char mask; /* Default 0 */
1453d58139fSopenharmony_ci} SecBracketTable;
1463d58139fSopenharmony_ci
1473d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
1483d58139fSopenharmony_ci#define SECUREC_INIT_BRACKET_TABLE { NULL, 0 }
1493d58139fSopenharmony_ci#else
1503d58139fSopenharmony_ci#define SECUREC_INIT_BRACKET_TABLE { {0}, 0 }
1513d58139fSopenharmony_ci#endif
1523d58139fSopenharmony_ci
1533d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT
1543d58139fSopenharmony_citypedef struct {
1553d58139fSopenharmony_ci    size_t floatStrTotalLen;       /* Initialization must be length of buffer in charater */
1563d58139fSopenharmony_ci    size_t floatStrUsedLen;        /* Store float string len */
1573d58139fSopenharmony_ci    SecChar *floatStr;             /* Initialization must point to buffer */
1583d58139fSopenharmony_ci    SecChar *allocatedFloatStr;    /* Initialization must be NULL  to store alloced point */
1593d58139fSopenharmony_ci    SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1];
1603d58139fSopenharmony_ci} SecFloatSpec;
1613d58139fSopenharmony_ci#endif
1623d58139fSopenharmony_ci
1633d58139fSopenharmony_ci#define SECUREC_NUMBER_STATE_DEFAULT 0U
1643d58139fSopenharmony_ci#define SECUREC_NUMBER_STATE_STARTED 1U
1653d58139fSopenharmony_ci
1663d58139fSopenharmony_citypedef struct {
1673d58139fSopenharmony_ci    SecInt ch;            /* Char read from input */
1683d58139fSopenharmony_ci    int charCount;        /* Number of characters processed */
1693d58139fSopenharmony_ci    void *argPtr;         /* Variable parameter pointer, point to the end of the string */
1703d58139fSopenharmony_ci    size_t arrayWidth;    /* Length of pointer Variable parameter, in charaters */
1713d58139fSopenharmony_ci    SecUnsignedInt64 number64; /* Store input number64 value */
1723d58139fSopenharmony_ci    unsigned long number; /* Store input number32 value */
1733d58139fSopenharmony_ci    int numberWidth;      /* 0 = SHORT, 1 = int, > 1  long or L_DOUBLE */
1743d58139fSopenharmony_ci    int numberArgType;       /* 1 for 64-bit integer, 0 otherwise. use it as decode function index */
1753d58139fSopenharmony_ci    unsigned int negative;         /* 0 is positive */
1763d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
1773d58139fSopenharmony_ci    unsigned int beyondMax;        /* Non-zero means beyond */
1783d58139fSopenharmony_ci#endif
1793d58139fSopenharmony_ci    unsigned int numberState; /* Identifies whether to start processing numbers, 1 is can input number */
1803d58139fSopenharmony_ci    int width;            /* Width number in format */
1813d58139fSopenharmony_ci    int widthSet;         /* 0 is not set width in format */
1823d58139fSopenharmony_ci    int convChr;          /* Lowercase format conversion characters */
1833d58139fSopenharmony_ci    int oriConvChr;       /* Store  original format conversion, convChr may change when parsing integers */
1843d58139fSopenharmony_ci    signed char isWCharOrLong;  /* -1/0 not wchar or long, 1 for wchar or long */
1853d58139fSopenharmony_ci    unsigned char suppress;     /* 0 is not have %* in format */
1863d58139fSopenharmony_ci} SecScanSpec;
1873d58139fSopenharmony_ci
1883d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
1893d58139fSopenharmony_ci#define SECUREC_GETC fgetwc
1903d58139fSopenharmony_ci#define SECUREC_UN_GETC ungetwc
1913d58139fSopenharmony_ci/* Only supports wide characters with a maximum length of two bytes in format string */
1923d58139fSopenharmony_ci#define SECUREC_BRACKET_CHAR_MASK 0xffffU
1933d58139fSopenharmony_ci#else
1943d58139fSopenharmony_ci#define SECUREC_GETC fgetc
1953d58139fSopenharmony_ci#define SECUREC_UN_GETC ungetc
1963d58139fSopenharmony_ci#define SECUREC_BRACKET_CHAR_MASK 0xffU
1973d58139fSopenharmony_ci#endif
1983d58139fSopenharmony_ci
1993d58139fSopenharmony_ci#define SECUREC_CHAR_SIZE ((unsigned int)(sizeof(SecChar)))
2003d58139fSopenharmony_ci/* To avoid 648, mask high bit: 0x00ffffff 0x0000ffff or 0x00000000 */
2013d58139fSopenharmony_ci#define SECUREC_CHAR_MASK_HIGH (((((((((unsigned int)(-1) >> SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
2023d58139fSopenharmony_ci    SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
2033d58139fSopenharmony_ci    SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
2043d58139fSopenharmony_ci    SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE)
2053d58139fSopenharmony_ci
2063d58139fSopenharmony_ci/* For char is 0xff, wcahr_t is 0xffff or 0xffffffff. */
2073d58139fSopenharmony_ci#define SECUREC_CHAR_MASK (~((((((((((unsigned int)(-1) & SECUREC_CHAR_MASK_HIGH) << \
2083d58139fSopenharmony_ci    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
2093d58139fSopenharmony_ci    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
2103d58139fSopenharmony_ci    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
2113d58139fSopenharmony_ci    SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE))
2123d58139fSopenharmony_ci
2133d58139fSopenharmony_ci/* According wchar_t has multiple bytes, so use sizeof */
2143d58139fSopenharmony_ci#define SECUREC_GET_CHAR(stream, outCh) do { \
2153d58139fSopenharmony_ci    if ((stream)->count >= sizeof(SecChar)) { \
2163d58139fSopenharmony_ci        *(outCh) = (SecInt)(SECUREC_CHAR_MASK & \
2173d58139fSopenharmony_ci            (unsigned int)(int)(*((const SecChar *)(const void *)(stream)->cur))); \
2183d58139fSopenharmony_ci        (stream)->cur += sizeof(SecChar); \
2193d58139fSopenharmony_ci        (stream)->count -= sizeof(SecChar); \
2203d58139fSopenharmony_ci    } else { \
2213d58139fSopenharmony_ci        *(outCh) = SECUREC_EOF; \
2223d58139fSopenharmony_ci    } \
2233d58139fSopenharmony_ci} SECUREC_WHILE_ZERO
2243d58139fSopenharmony_ci
2253d58139fSopenharmony_ci#define SECUREC_UN_GET_CHAR(stream) do { \
2263d58139fSopenharmony_ci    if ((stream)->cur > (stream)->base) { \
2273d58139fSopenharmony_ci        (stream)->cur -= sizeof(SecChar); \
2283d58139fSopenharmony_ci        (stream)->count += sizeof(SecChar); \
2293d58139fSopenharmony_ci    } \
2303d58139fSopenharmony_ci} SECUREC_WHILE_ZERO
2313d58139fSopenharmony_ci
2323d58139fSopenharmony_ci/* Convert wchar_t to int and then to unsigned int  to keep data clearing warning */
2333d58139fSopenharmony_ci#define SECUREC_TO_LOWERCASE(chr) ((int)((unsigned int)(int)(chr) | (unsigned int)('a' - 'A')))
2343d58139fSopenharmony_ci
2353d58139fSopenharmony_ci/* Record a flag for each bit */
2363d58139fSopenharmony_ci#define SECUREC_BRACKET_INDEX(x)  ((unsigned int)(x) >> 3U)
2373d58139fSopenharmony_ci#define SECUREC_BRACKET_VALUE(x)  ((unsigned char)(1U << ((unsigned int)(x) & 7U)))
2383d58139fSopenharmony_ci#if SECUREC_IN_KERNEL
2393d58139fSopenharmony_ci#define SECUREC_CONVERT_IS_UNSIGNED(conv) ((conv) == 'x' || (conv) == 'o' || (conv) == 'u')
2403d58139fSopenharmony_ci#endif
2413d58139fSopenharmony_ci
2423d58139fSopenharmony_ci/*
2433d58139fSopenharmony_ci * Set char in %[xxx] into table, only supports wide characters with a maximum length of two bytes
2443d58139fSopenharmony_ci */
2453d58139fSopenharmony_ciSECUREC_INLINE void SecBracketSetBit(unsigned char *table, SecUnsignedChar ch)
2463d58139fSopenharmony_ci{
2473d58139fSopenharmony_ci    unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
2483d58139fSopenharmony_ci    unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
2493d58139fSopenharmony_ci    /* Do not use   |=   optimize this code, it will cause compiling warning */
2503d58139fSopenharmony_ci    table[tableIndex] = (unsigned char)(table[tableIndex] | tableValue);
2513d58139fSopenharmony_ci}
2523d58139fSopenharmony_ci
2533d58139fSopenharmony_ciSECUREC_INLINE void SecBracketSetBitRange(unsigned char *table, SecUnsignedChar startCh, SecUnsignedChar endCh)
2543d58139fSopenharmony_ci{
2553d58139fSopenharmony_ci    SecUnsignedChar expCh;
2563d58139fSopenharmony_ci    /* %[a-z] %[a-a] Format %[a-\xff] end is 0xFF, condition (expCh <= endChar) cause dead loop */
2573d58139fSopenharmony_ci    for (expCh = startCh; expCh < endCh; ++expCh) {
2583d58139fSopenharmony_ci        SecBracketSetBit(table, expCh);
2593d58139fSopenharmony_ci    }
2603d58139fSopenharmony_ci    SecBracketSetBit(table, endCh);
2613d58139fSopenharmony_ci}
2623d58139fSopenharmony_ci/*
2633d58139fSopenharmony_ci * Determine whether the expression can be satisfied
2643d58139fSopenharmony_ci */
2653d58139fSopenharmony_ciSECUREC_INLINE int SecCanInputForBracket(int convChr, SecInt ch, const SecBracketTable *bracketTable)
2663d58139fSopenharmony_ci{
2673d58139fSopenharmony_ci    unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
2683d58139fSopenharmony_ci    unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
2693d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
2703d58139fSopenharmony_ci    if (((unsigned int)(int)ch & (~(SECUREC_BRACKET_CHAR_MASK))) != 0) {
2713d58139fSopenharmony_ci        /* The value of the wide character exceeds the size of two bytes */
2723d58139fSopenharmony_ci        return 0;
2733d58139fSopenharmony_ci    }
2743d58139fSopenharmony_ci    return (int)(convChr == SECUREC_BRACE &&
2753d58139fSopenharmony_ci        (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0);
2763d58139fSopenharmony_ci#else
2773d58139fSopenharmony_ci    return (int)(convChr == SECUREC_BRACE &&
2783d58139fSopenharmony_ci        (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0);
2793d58139fSopenharmony_ci#endif
2803d58139fSopenharmony_ci}
2813d58139fSopenharmony_ci
2823d58139fSopenharmony_ci/*
2833d58139fSopenharmony_ci * String input ends when blank character is encountered
2843d58139fSopenharmony_ci */
2853d58139fSopenharmony_ciSECUREC_INLINE int SecCanInputString(int convChr, SecInt ch)
2863d58139fSopenharmony_ci{
2873d58139fSopenharmony_ci    return (int)(convChr == 's' &&
2883d58139fSopenharmony_ci        (!(ch >= SECUREC_CHAR('\t') && ch <= SECUREC_CHAR('\r')) && ch != SECUREC_CHAR(' ')));
2893d58139fSopenharmony_ci}
2903d58139fSopenharmony_ci
2913d58139fSopenharmony_ci/*
2923d58139fSopenharmony_ci * Can input a character when format is %c
2933d58139fSopenharmony_ci */
2943d58139fSopenharmony_ciSECUREC_INLINE int SecCanInputCharacter(int convChr)
2953d58139fSopenharmony_ci{
2963d58139fSopenharmony_ci    return (int)(convChr == 'c');
2973d58139fSopenharmony_ci}
2983d58139fSopenharmony_ci
2993d58139fSopenharmony_ci/*
3003d58139fSopenharmony_ci * Determine if it is a 64-bit pointer  function
3013d58139fSopenharmony_ci * Return 0 is not ,1 is 64bit pointer
3023d58139fSopenharmony_ci */
3033d58139fSopenharmony_ciSECUREC_INLINE int SecNumberArgType(size_t sizeOfVoidStar)
3043d58139fSopenharmony_ci{
3053d58139fSopenharmony_ci    /* Point size is 4 or 8 , Under the 64 bit system, the value not 0 */
3063d58139fSopenharmony_ci    /* To clear e778 */
3073d58139fSopenharmony_ci    if ((sizeOfVoidStar & sizeof(SecInt64)) != 0) {
3083d58139fSopenharmony_ci        return 1;
3093d58139fSopenharmony_ci    }
3103d58139fSopenharmony_ci    return 0;
3113d58139fSopenharmony_ci}
3123d58139fSopenharmony_ciSECUREC_INLINE int SecIsDigit(SecInt ch);
3133d58139fSopenharmony_ciSECUREC_INLINE int SecIsXdigit(SecInt ch);
3143d58139fSopenharmony_ciSECUREC_INLINE int SecIsSpace(SecInt ch);
3153d58139fSopenharmony_ciSECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter);
3163d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter);
3173d58139fSopenharmony_ciSECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter);
3183d58139fSopenharmony_ci
3193d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT
3203d58139fSopenharmony_ci
3213d58139fSopenharmony_ci/*
3223d58139fSopenharmony_ci * Convert a floating point string to a floating point number
3233d58139fSopenharmony_ci */
3243d58139fSopenharmony_ciSECUREC_INLINE int SecAssignNarrowFloat(const char *floatStr, const SecScanSpec *spec)
3253d58139fSopenharmony_ci{
3263d58139fSopenharmony_ci    char *endPtr = NULL;
3273d58139fSopenharmony_ci    double d;
3283d58139fSopenharmony_ci#if SECUREC_SUPPORT_STRTOLD
3293d58139fSopenharmony_ci    if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG_LONG) {
3303d58139fSopenharmony_ci        long double d2 = strtold(floatStr, &endPtr);
3313d58139fSopenharmony_ci        if (endPtr == floatStr) {
3323d58139fSopenharmony_ci            return -1;
3333d58139fSopenharmony_ci        }
3343d58139fSopenharmony_ci        *(long double UNALIGNED *)(spec->argPtr) = d2;
3353d58139fSopenharmony_ci        return 0;
3363d58139fSopenharmony_ci    }
3373d58139fSopenharmony_ci#endif
3383d58139fSopenharmony_ci    d = strtod(floatStr, &endPtr);
3393d58139fSopenharmony_ci    /* cannot detect if endPtr points to the end of floatStr,because strtod handles only two characters for 1.E */
3403d58139fSopenharmony_ci    if (endPtr == floatStr) {
3413d58139fSopenharmony_ci        return -1;
3423d58139fSopenharmony_ci    }
3433d58139fSopenharmony_ci    if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) {
3443d58139fSopenharmony_ci        *(double UNALIGNED *)(spec->argPtr) = (double)d;
3453d58139fSopenharmony_ci    } else {
3463d58139fSopenharmony_ci        *(float UNALIGNED *)(spec->argPtr) = (float)d;
3473d58139fSopenharmony_ci    }
3483d58139fSopenharmony_ci    return 0;
3493d58139fSopenharmony_ci}
3503d58139fSopenharmony_ci
3513d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
3523d58139fSopenharmony_ci/*
3533d58139fSopenharmony_ci * Convert a floating point wchar string to a floating point number
3543d58139fSopenharmony_ci * Success  ret 0
3553d58139fSopenharmony_ci */
3563d58139fSopenharmony_ciSECUREC_INLINE int SecAssignWideFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
3573d58139fSopenharmony_ci{
3583d58139fSopenharmony_ci    int retVal;
3593d58139fSopenharmony_ci    /* Convert float string */
3603d58139fSopenharmony_ci    size_t mbsLen;
3613d58139fSopenharmony_ci    size_t tempFloatStrLen = (size_t)(floatSpec->floatStrUsedLen + 1) * sizeof(wchar_t);
3623d58139fSopenharmony_ci    char *tempFloatStr = (char *)SECUREC_MALLOC(tempFloatStrLen);
3633d58139fSopenharmony_ci    if (tempFloatStr == NULL) {
3643d58139fSopenharmony_ci        return -1;
3653d58139fSopenharmony_ci    }
3663d58139fSopenharmony_ci    tempFloatStr[0] = '\0';
3673d58139fSopenharmony_ci    SECUREC_MASK_MSVC_CRT_WARNING
3683d58139fSopenharmony_ci    mbsLen = wcstombs(tempFloatStr, floatSpec->floatStr, tempFloatStrLen - 1);
3693d58139fSopenharmony_ci    SECUREC_END_MASK_MSVC_CRT_WARNING
3703d58139fSopenharmony_ci    /* This condition must satisfy mbsLen is not -1 */
3713d58139fSopenharmony_ci    if (mbsLen >= tempFloatStrLen) {
3723d58139fSopenharmony_ci        SECUREC_FREE(tempFloatStr);
3733d58139fSopenharmony_ci        return -1;
3743d58139fSopenharmony_ci    }
3753d58139fSopenharmony_ci    tempFloatStr[mbsLen] = '\0';
3763d58139fSopenharmony_ci    retVal = SecAssignNarrowFloat(tempFloatStr, spec);
3773d58139fSopenharmony_ci    SECUREC_FREE(tempFloatStr);
3783d58139fSopenharmony_ci    return retVal;
3793d58139fSopenharmony_ci}
3803d58139fSopenharmony_ci#endif
3813d58139fSopenharmony_ci
3823d58139fSopenharmony_ciSECUREC_INLINE int SecAssignFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
3833d58139fSopenharmony_ci{
3843d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
3853d58139fSopenharmony_ci    return SecAssignWideFloat(floatSpec, spec);
3863d58139fSopenharmony_ci#else
3873d58139fSopenharmony_ci    return SecAssignNarrowFloat(floatSpec->floatStr, spec);
3883d58139fSopenharmony_ci#endif
3893d58139fSopenharmony_ci}
3903d58139fSopenharmony_ci
3913d58139fSopenharmony_ci/*
3923d58139fSopenharmony_ci * Init SecFloatSpec before parse format
3933d58139fSopenharmony_ci */
3943d58139fSopenharmony_ciSECUREC_INLINE void SecInitFloatSpec(SecFloatSpec *floatSpec)
3953d58139fSopenharmony_ci{
3963d58139fSopenharmony_ci    floatSpec->floatStr = floatSpec->buffer;
3973d58139fSopenharmony_ci    floatSpec->allocatedFloatStr = NULL;
3983d58139fSopenharmony_ci    floatSpec->floatStrTotalLen = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]);
3993d58139fSopenharmony_ci    floatSpec->floatStrUsedLen = 0;
4003d58139fSopenharmony_ci}
4013d58139fSopenharmony_ci
4023d58139fSopenharmony_ciSECUREC_INLINE void SecFreeFloatSpec(SecFloatSpec *floatSpec, int *doneCount)
4033d58139fSopenharmony_ci{
4043d58139fSopenharmony_ci    /* 2014.3.6 add, clear the stack data */
4053d58139fSopenharmony_ci    if (memset_s(floatSpec->buffer, sizeof(floatSpec->buffer), 0, sizeof(floatSpec->buffer)) != EOK) {
4063d58139fSopenharmony_ci        *doneCount = 0; /* This code just to meet the coding requirements */
4073d58139fSopenharmony_ci    }
4083d58139fSopenharmony_ci    /* The pFloatStr can be alloced in SecExtendFloatLen function, clear and free it */
4093d58139fSopenharmony_ci    if (floatSpec->allocatedFloatStr != NULL) {
4103d58139fSopenharmony_ci        size_t bufferSize = floatSpec->floatStrTotalLen * sizeof(SecChar);
4113d58139fSopenharmony_ci        if (memset_s(floatSpec->allocatedFloatStr, bufferSize, 0, bufferSize) != EOK) {
4123d58139fSopenharmony_ci            *doneCount = 0; /* This code just to meet the coding requirements */
4133d58139fSopenharmony_ci        }
4143d58139fSopenharmony_ci        SECUREC_FREE(floatSpec->allocatedFloatStr);
4153d58139fSopenharmony_ci        floatSpec->allocatedFloatStr = NULL;
4163d58139fSopenharmony_ci        floatSpec->floatStr = NULL;
4173d58139fSopenharmony_ci    }
4183d58139fSopenharmony_ci}
4193d58139fSopenharmony_ci
4203d58139fSopenharmony_ci/*
4213d58139fSopenharmony_ci * Splice floating point string
4223d58139fSopenharmony_ci * Return 0 OK
4233d58139fSopenharmony_ci */
4243d58139fSopenharmony_ciSECUREC_INLINE int SecExtendFloatLen(SecFloatSpec *floatSpec)
4253d58139fSopenharmony_ci{
4263d58139fSopenharmony_ci    if (floatSpec->floatStrUsedLen >= floatSpec->floatStrTotalLen) {
4273d58139fSopenharmony_ci        /* Buffer size is len x sizeof(SecChar) */
4283d58139fSopenharmony_ci        size_t oriSize = floatSpec->floatStrTotalLen * sizeof(SecChar);
4293d58139fSopenharmony_ci        /* Add one character to clear tool warning */
4303d58139fSopenharmony_ci        size_t nextSize = (oriSize * 2) + sizeof(SecChar); /* Multiply 2 to extend buffer size */
4313d58139fSopenharmony_ci
4323d58139fSopenharmony_ci        /* Prevents integer overflow, the maximum length of SECUREC_MAX_WIDTH_LEN is enough */
4333d58139fSopenharmony_ci        if (nextSize <= (size_t)SECUREC_MAX_WIDTH_LEN) {
4343d58139fSopenharmony_ci            void *nextBuffer = (void *)SECUREC_MALLOC(nextSize);
4353d58139fSopenharmony_ci            if (nextBuffer == NULL) {
4363d58139fSopenharmony_ci                return -1;
4373d58139fSopenharmony_ci            }
4383d58139fSopenharmony_ci            if (memcpy_s(nextBuffer, nextSize, floatSpec->floatStr, oriSize) != EOK) {
4393d58139fSopenharmony_ci                SECUREC_FREE(nextBuffer);   /* This is a dead code, just to meet the coding requirements */
4403d58139fSopenharmony_ci                return -1;
4413d58139fSopenharmony_ci            }
4423d58139fSopenharmony_ci            /* Clear old buffer memory */
4433d58139fSopenharmony_ci            if (memset_s(floatSpec->floatStr, oriSize, 0, oriSize) != EOK) {
4443d58139fSopenharmony_ci                SECUREC_FREE(nextBuffer);   /* This is a dead code, just to meet the coding requirements */
4453d58139fSopenharmony_ci                return -1;
4463d58139fSopenharmony_ci            }
4473d58139fSopenharmony_ci            /* Free old allocated buffer */
4483d58139fSopenharmony_ci            if (floatSpec->allocatedFloatStr != NULL) {
4493d58139fSopenharmony_ci                SECUREC_FREE(floatSpec->allocatedFloatStr);
4503d58139fSopenharmony_ci            }
4513d58139fSopenharmony_ci            floatSpec->allocatedFloatStr = (SecChar *)(nextBuffer);    /* Use to clear free on stack warning */
4523d58139fSopenharmony_ci            floatSpec->floatStr = (SecChar *)(nextBuffer);
4533d58139fSopenharmony_ci            floatSpec->floatStrTotalLen = nextSize / sizeof(SecChar); /* Get buffer total len in character */
4543d58139fSopenharmony_ci            return 0;
4553d58139fSopenharmony_ci        }
4563d58139fSopenharmony_ci        return -1; /* Next size is beyond max */
4573d58139fSopenharmony_ci    }
4583d58139fSopenharmony_ci    return 0;
4593d58139fSopenharmony_ci}
4603d58139fSopenharmony_ci
4613d58139fSopenharmony_ci/* Do not use localeconv()->decimal_pointif  only support  '.' */
4623d58139fSopenharmony_ciSECUREC_INLINE int SecIsFloatDecimal(SecChar ch)
4633d58139fSopenharmony_ci{
4643d58139fSopenharmony_ci    return (int)(ch == SECUREC_CHAR('.'));
4653d58139fSopenharmony_ci}
4663d58139fSopenharmony_ci
4673d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatSign(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
4683d58139fSopenharmony_ci{
4693d58139fSopenharmony_ci    if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) {
4703d58139fSopenharmony_ci        return 0;
4713d58139fSopenharmony_ci    }
4723d58139fSopenharmony_ci    spec->ch = SecGetChar(stream, &(spec->charCount));
4733d58139fSopenharmony_ci    if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
4743d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec); /* Make sure the count after un get char is correct */
4753d58139fSopenharmony_ci        if (spec->ch == SECUREC_CHAR('-')) {
4763d58139fSopenharmony_ci            floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('-');
4773d58139fSopenharmony_ci            ++floatSpec->floatStrUsedLen;
4783d58139fSopenharmony_ci            if (SecExtendFloatLen(floatSpec) != 0) {
4793d58139fSopenharmony_ci                return -1;
4803d58139fSopenharmony_ci            }
4813d58139fSopenharmony_ci        }
4823d58139fSopenharmony_ci    } else {
4833d58139fSopenharmony_ci        SecUnGetChar(spec->ch, stream, &(spec->charCount));
4843d58139fSopenharmony_ci    }
4853d58139fSopenharmony_ci    return 0;
4863d58139fSopenharmony_ci}
4873d58139fSopenharmony_ci
4883d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatDigit(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
4893d58139fSopenharmony_ci{
4903d58139fSopenharmony_ci    /* Now get integral part */
4913d58139fSopenharmony_ci    while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
4923d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount));
4933d58139fSopenharmony_ci        if (SecIsDigit(spec->ch) == 0) {
4943d58139fSopenharmony_ci            SecUnGetChar(spec->ch, stream, &(spec->charCount));
4953d58139fSopenharmony_ci            return 0;
4963d58139fSopenharmony_ci        }
4973d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
4983d58139fSopenharmony_ci        spec->numberState = SECUREC_NUMBER_STATE_STARTED;
4993d58139fSopenharmony_ci        floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch;
5003d58139fSopenharmony_ci        ++floatSpec->floatStrUsedLen;
5013d58139fSopenharmony_ci        if (SecExtendFloatLen(floatSpec) != 0) {
5023d58139fSopenharmony_ci            return -1;
5033d58139fSopenharmony_ci        }
5043d58139fSopenharmony_ci    }
5053d58139fSopenharmony_ci    return 0;
5063d58139fSopenharmony_ci}
5073d58139fSopenharmony_ci
5083d58139fSopenharmony_ci/*
5093d58139fSopenharmony_ci* Scan value of exponent.
5103d58139fSopenharmony_ci* Return 0 OK
5113d58139fSopenharmony_ci*/
5123d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
5133d58139fSopenharmony_ci{
5143d58139fSopenharmony_ci    if (SecInputFloatSign(stream, spec, floatSpec) == -1) {
5153d58139fSopenharmony_ci        return -1;
5163d58139fSopenharmony_ci    }
5173d58139fSopenharmony_ci    if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
5183d58139fSopenharmony_ci        return -1;
5193d58139fSopenharmony_ci    }
5203d58139fSopenharmony_ci    return 0;
5213d58139fSopenharmony_ci}
5223d58139fSopenharmony_ci
5233d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatFractional(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
5243d58139fSopenharmony_ci{
5253d58139fSopenharmony_ci    if (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
5263d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount));
5273d58139fSopenharmony_ci        if (SecIsFloatDecimal((SecChar)spec->ch) == 0) {
5283d58139fSopenharmony_ci            SecUnGetChar(spec->ch, stream, &(spec->charCount));
5293d58139fSopenharmony_ci            return 0;
5303d58139fSopenharmony_ci        }
5313d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
5323d58139fSopenharmony_ci        /* Now check for decimal */
5333d58139fSopenharmony_ci        floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch;
5343d58139fSopenharmony_ci        ++floatSpec->floatStrUsedLen;
5353d58139fSopenharmony_ci        if (SecExtendFloatLen(floatSpec) != 0) {
5363d58139fSopenharmony_ci            return -1;
5373d58139fSopenharmony_ci        }
5383d58139fSopenharmony_ci        if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
5393d58139fSopenharmony_ci            return -1;
5403d58139fSopenharmony_ci        }
5413d58139fSopenharmony_ci    }
5423d58139fSopenharmony_ci    return 0;
5433d58139fSopenharmony_ci}
5443d58139fSopenharmony_ci
5453d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloatExponent(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
5463d58139fSopenharmony_ci{
5473d58139fSopenharmony_ci    /* Now get exponent part */
5483d58139fSopenharmony_ci    if (spec->numberState == SECUREC_NUMBER_STATE_STARTED && SECUREC_FILED_WIDTH_ENOUGH(spec)) {
5493d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount));
5503d58139fSopenharmony_ci        if (spec->ch != SECUREC_CHAR('e') && spec->ch != SECUREC_CHAR('E')) {
5513d58139fSopenharmony_ci            SecUnGetChar(spec->ch, stream, &(spec->charCount));
5523d58139fSopenharmony_ci            return 0;
5533d58139fSopenharmony_ci        }
5543d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
5553d58139fSopenharmony_ci        floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('e');
5563d58139fSopenharmony_ci        ++floatSpec->floatStrUsedLen;
5573d58139fSopenharmony_ci        if (SecExtendFloatLen(floatSpec) != 0) {
5583d58139fSopenharmony_ci            return -1;
5593d58139fSopenharmony_ci        }
5603d58139fSopenharmony_ci        if (SecInputFloatE(stream, spec, floatSpec) != 0) {
5613d58139fSopenharmony_ci            return -1;
5623d58139fSopenharmony_ci        }
5633d58139fSopenharmony_ci    }
5643d58139fSopenharmony_ci    return 0;
5653d58139fSopenharmony_ci}
5663d58139fSopenharmony_ci
5673d58139fSopenharmony_ci/*
5683d58139fSopenharmony_ci* Scan %f.
5693d58139fSopenharmony_ci* Return 0 OK
5703d58139fSopenharmony_ci*/
5713d58139fSopenharmony_ciSECUREC_INLINE int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
5723d58139fSopenharmony_ci{
5733d58139fSopenharmony_ci    floatSpec->floatStrUsedLen = 0;
5743d58139fSopenharmony_ci
5753d58139fSopenharmony_ci    /* The following code sequence is strict */
5763d58139fSopenharmony_ci    if (SecInputFloatSign(stream, spec, floatSpec) != 0) {
5773d58139fSopenharmony_ci        return -1;
5783d58139fSopenharmony_ci    }
5793d58139fSopenharmony_ci    if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
5803d58139fSopenharmony_ci        return -1;
5813d58139fSopenharmony_ci    }
5823d58139fSopenharmony_ci    if (SecInputFloatFractional(stream, spec, floatSpec) != 0) {
5833d58139fSopenharmony_ci        return -1;
5843d58139fSopenharmony_ci    }
5853d58139fSopenharmony_ci    if (SecInputFloatExponent(stream, spec, floatSpec) != 0) {
5863d58139fSopenharmony_ci        return -1;
5873d58139fSopenharmony_ci    }
5883d58139fSopenharmony_ci
5893d58139fSopenharmony_ci    /* Make sure  have a string terminator, buffer is large enough */
5903d58139fSopenharmony_ci    floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0');
5913d58139fSopenharmony_ci    if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) {
5923d58139fSopenharmony_ci        return 0;
5933d58139fSopenharmony_ci    }
5943d58139fSopenharmony_ci    return -1;
5953d58139fSopenharmony_ci}
5963d58139fSopenharmony_ci#endif
5973d58139fSopenharmony_ci
5983d58139fSopenharmony_ci#if (!defined(SECUREC_FOR_WCHAR) && SECUREC_HAVE_WCHART && SECUREC_HAVE_MBTOWC) || \
5993d58139fSopenharmony_ci    (!defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION))
6003d58139fSopenharmony_ci/* only multi-bytes string need isleadbyte() function */
6013d58139fSopenharmony_ciSECUREC_INLINE int SecIsLeadByte(SecInt ch)
6023d58139fSopenharmony_ci{
6033d58139fSopenharmony_ci    unsigned int c = (unsigned int)ch;
6043d58139fSopenharmony_ci#if !(defined(_MSC_VER) || defined(_INC_WCTYPE))
6053d58139fSopenharmony_ci    return (int)(c & 0x80U); /* Use bitwise operation to check if the most significant bit is 1 */
6063d58139fSopenharmony_ci#else
6073d58139fSopenharmony_ci    return (int)isleadbyte((int)(c & 0xffU)); /* Use bitwise operations to limit character values to valid ranges */
6083d58139fSopenharmony_ci#endif
6093d58139fSopenharmony_ci}
6103d58139fSopenharmony_ci#endif
6113d58139fSopenharmony_ci
6123d58139fSopenharmony_ci/*
6133d58139fSopenharmony_ci * Parsing whether it is a wide character
6143d58139fSopenharmony_ci */
6153d58139fSopenharmony_ciSECUREC_INLINE void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec)
6163d58139fSopenharmony_ci{
6173d58139fSopenharmony_ci    if (spec->isWCharOrLong != 0) {
6183d58139fSopenharmony_ci        /* Wide character identifiers have been explicitly set by l or h flag */
6193d58139fSopenharmony_ci        return;
6203d58139fSopenharmony_ci    }
6213d58139fSopenharmony_ci
6223d58139fSopenharmony_ci    /* Set default flag */
6233d58139fSopenharmony_ci#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT)
6243d58139fSopenharmony_ci    spec->isWCharOrLong = 1;  /* On windows wide char version %c %s %[ is wide char */
6253d58139fSopenharmony_ci#else
6263d58139fSopenharmony_ci    spec->isWCharOrLong = -1; /* On linux all version %c %s %[ is multi char */
6273d58139fSopenharmony_ci#endif
6283d58139fSopenharmony_ci
6293d58139fSopenharmony_ci    if (ch == SECUREC_CHAR('C') || ch == SECUREC_CHAR('S')) {
6303d58139fSopenharmony_ci#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT)
6313d58139fSopenharmony_ci        spec->isWCharOrLong = -1; /* On windows wide char version %C %S is multi char */
6323d58139fSopenharmony_ci#else
6333d58139fSopenharmony_ci        spec->isWCharOrLong = 1;  /* On linux all version %C %S is wide char */
6343d58139fSopenharmony_ci#endif
6353d58139fSopenharmony_ci    }
6363d58139fSopenharmony_ci
6373d58139fSopenharmony_ci    return;
6383d58139fSopenharmony_ci}
6393d58139fSopenharmony_ci/*
6403d58139fSopenharmony_ci * Decode  %l %ll
6413d58139fSopenharmony_ci */
6423d58139fSopenharmony_ciSECUREC_INLINE void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec)
6433d58139fSopenharmony_ci{
6443d58139fSopenharmony_ci    const SecUnsignedChar *fmt = *format;
6453d58139fSopenharmony_ci    if (*(fmt + 1) == SECUREC_CHAR('l')) {
6463d58139fSopenharmony_ci        spec->numberArgType = 1;
6473d58139fSopenharmony_ci        spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
6483d58139fSopenharmony_ci        ++fmt;
6493d58139fSopenharmony_ci    } else {
6503d58139fSopenharmony_ci        spec->numberWidth = SECUREC_NUM_WIDTH_LONG;
6513d58139fSopenharmony_ci#if defined(SECUREC_ON_64BITS) && !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
6523d58139fSopenharmony_ci        /* On window 64 system sizeof long is 32bit */
6533d58139fSopenharmony_ci        spec->numberArgType = 1;
6543d58139fSopenharmony_ci#endif
6553d58139fSopenharmony_ci        spec->isWCharOrLong = 1;
6563d58139fSopenharmony_ci    }
6573d58139fSopenharmony_ci    *format = fmt;
6583d58139fSopenharmony_ci}
6593d58139fSopenharmony_ci
6603d58139fSopenharmony_ci/*
6613d58139fSopenharmony_ci * Decode  %I %I43 %I64 %Id %Ii %Io ...
6623d58139fSopenharmony_ci * Set finishFlag to  1  finish Flag
6633d58139fSopenharmony_ci */
6643d58139fSopenharmony_ciSECUREC_INLINE void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
6653d58139fSopenharmony_ci{
6663d58139fSopenharmony_ci    const SecUnsignedChar *fmt = *format;
6673d58139fSopenharmony_ci    if ((*(fmt + 1) == SECUREC_CHAR('6')) &&
6683d58139fSopenharmony_ci        (*(fmt + 2) == SECUREC_CHAR('4'))) { /* Offset 2 for I64 */
6693d58139fSopenharmony_ci        spec->numberArgType = 1;
6703d58139fSopenharmony_ci        *format = *format + 2; /* Add 2 to skip I64 point to '4' next loop will inc */
6713d58139fSopenharmony_ci    } else if ((*(fmt + 1) == SECUREC_CHAR('3')) &&
6723d58139fSopenharmony_ci                (*(fmt + 2) == SECUREC_CHAR('2'))) { /* Offset 2 for I32 */
6733d58139fSopenharmony_ci        *format = *format + 2; /* Add 2 to skip I32 point to '2' next loop will inc */
6743d58139fSopenharmony_ci    } else if ((*(fmt + 1) == SECUREC_CHAR('d')) ||
6753d58139fSopenharmony_ci                (*(fmt + 1) == SECUREC_CHAR('i')) ||
6763d58139fSopenharmony_ci                (*(fmt + 1) == SECUREC_CHAR('o')) ||
6773d58139fSopenharmony_ci                (*(fmt + 1) == SECUREC_CHAR('x')) ||
6783d58139fSopenharmony_ci                (*(fmt + 1) == SECUREC_CHAR('X'))) {
6793d58139fSopenharmony_ci        spec->numberArgType = SecNumberArgType(sizeof(void *));
6803d58139fSopenharmony_ci    } else {
6813d58139fSopenharmony_ci        /* For %I */
6823d58139fSopenharmony_ci        spec->numberArgType = SecNumberArgType(sizeof(void *));
6833d58139fSopenharmony_ci        *finishFlag = 1;
6843d58139fSopenharmony_ci    }
6853d58139fSopenharmony_ci}
6863d58139fSopenharmony_ci
6873d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec)
6883d58139fSopenharmony_ci{
6893d58139fSopenharmony_ci    const SecUnsignedChar *fmt = *format;
6903d58139fSopenharmony_ci    while (SecIsDigit((SecInt)(int)(*fmt)) != 0) {
6913d58139fSopenharmony_ci        spec->widthSet = 1;
6923d58139fSopenharmony_ci        if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(spec->width)) {
6933d58139fSopenharmony_ci            return -1;
6943d58139fSopenharmony_ci        }
6953d58139fSopenharmony_ci        spec->width = (int)SECUREC_MUL_TEN((unsigned int)spec->width) + (unsigned char)(*fmt - SECUREC_CHAR('0'));
6963d58139fSopenharmony_ci        ++fmt;
6973d58139fSopenharmony_ci    }
6983d58139fSopenharmony_ci    *format = fmt;
6993d58139fSopenharmony_ci    return 0;
7003d58139fSopenharmony_ci}
7013d58139fSopenharmony_ci
7023d58139fSopenharmony_ci/*
7033d58139fSopenharmony_ci * Init default flags for each format. do not init ch this variable is context-dependent
7043d58139fSopenharmony_ci */
7053d58139fSopenharmony_ciSECUREC_INLINE void SecSetDefaultScanSpec(SecScanSpec *spec)
7063d58139fSopenharmony_ci{
7073d58139fSopenharmony_ci    /* The ch and charCount member variables cannot be initialized here */
7083d58139fSopenharmony_ci    spec->argPtr = NULL;
7093d58139fSopenharmony_ci    spec->arrayWidth = 0;
7103d58139fSopenharmony_ci    spec->number64 = 0;
7113d58139fSopenharmony_ci    spec->number = 0;
7123d58139fSopenharmony_ci    spec->numberWidth = SECUREC_NUM_WIDTH_INT;    /* 0 = SHORT, 1 = int, > 1  long or L_DOUBLE */
7133d58139fSopenharmony_ci    spec->numberArgType = 0;                         /* 1 for 64-bit integer, 0 otherwise */
7143d58139fSopenharmony_ci    spec->width = 0;
7153d58139fSopenharmony_ci    spec->widthSet = 0;
7163d58139fSopenharmony_ci    spec->convChr = 0;
7173d58139fSopenharmony_ci    spec->oriConvChr = 0;
7183d58139fSopenharmony_ci    spec->isWCharOrLong = 0;
7193d58139fSopenharmony_ci    spec->suppress = 0;
7203d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
7213d58139fSopenharmony_ci    spec->beyondMax = 0;
7223d58139fSopenharmony_ci#endif
7233d58139fSopenharmony_ci    spec->negative = 0;
7243d58139fSopenharmony_ci    spec->numberState = SECUREC_NUMBER_STATE_DEFAULT;
7253d58139fSopenharmony_ci}
7263d58139fSopenharmony_ci
7273d58139fSopenharmony_ci/*
7283d58139fSopenharmony_ci * Decode qualifier %I %L %h ...
7293d58139fSopenharmony_ci * Set finishFlag to  1  finish Flag
7303d58139fSopenharmony_ci */
7313d58139fSopenharmony_ciSECUREC_INLINE void  SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
7323d58139fSopenharmony_ci{
7333d58139fSopenharmony_ci    switch (**format) {
7343d58139fSopenharmony_ci        case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */
7353d58139fSopenharmony_ci        case SECUREC_CHAR('N'):
7363d58139fSopenharmony_ci            break;
7373d58139fSopenharmony_ci        case SECUREC_CHAR('h'):
7383d58139fSopenharmony_ci            --spec->numberWidth; /* The h for SHORT , hh for CHAR */
7393d58139fSopenharmony_ci            spec->isWCharOrLong = -1;
7403d58139fSopenharmony_ci            break;
7413d58139fSopenharmony_ci#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
7423d58139fSopenharmony_ci        case SECUREC_CHAR('j'):
7433d58139fSopenharmony_ci            spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;  /* For intmax_t or uintmax_t */
7443d58139fSopenharmony_ci            spec->numberArgType = 1;
7453d58139fSopenharmony_ci            break;
7463d58139fSopenharmony_ci        case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */
7473d58139fSopenharmony_ci#endif
7483d58139fSopenharmony_ci#if SECUREC_IN_KERNEL
7493d58139fSopenharmony_ci        case SECUREC_CHAR('Z'): /* fall-through */ /* FALLTHRU */
7503d58139fSopenharmony_ci#endif
7513d58139fSopenharmony_ci        case SECUREC_CHAR('z'):
7523d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
7533d58139fSopenharmony_ci            spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
7543d58139fSopenharmony_ci            spec->numberArgType = 1;
7553d58139fSopenharmony_ci#else
7563d58139fSopenharmony_ci            spec->numberWidth = SECUREC_NUM_WIDTH_LONG;
7573d58139fSopenharmony_ci#endif
7583d58139fSopenharmony_ci            break;
7593d58139fSopenharmony_ci        case SECUREC_CHAR('L'):    /* For long double */ /* fall-through */ /* FALLTHRU */
7603d58139fSopenharmony_ci        case SECUREC_CHAR('q'):
7613d58139fSopenharmony_ci            spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
7623d58139fSopenharmony_ci            spec->numberArgType = 1;
7633d58139fSopenharmony_ci            break;
7643d58139fSopenharmony_ci        case SECUREC_CHAR('l'):
7653d58139fSopenharmony_ci            SecDecodeScanQualifierL(format, spec);
7663d58139fSopenharmony_ci            break;
7673d58139fSopenharmony_ci        case SECUREC_CHAR('w'):
7683d58139fSopenharmony_ci            spec->isWCharOrLong = 1;
7693d58139fSopenharmony_ci            break;
7703d58139fSopenharmony_ci        case SECUREC_CHAR('*'):
7713d58139fSopenharmony_ci            spec->suppress = 1;
7723d58139fSopenharmony_ci            break;
7733d58139fSopenharmony_ci        case SECUREC_CHAR('I'):
7743d58139fSopenharmony_ci            SecDecodeScanQualifierI(format, spec, finishFlag);
7753d58139fSopenharmony_ci            break;
7763d58139fSopenharmony_ci        default:
7773d58139fSopenharmony_ci            *finishFlag = 1;
7783d58139fSopenharmony_ci            break;
7793d58139fSopenharmony_ci    }
7803d58139fSopenharmony_ci}
7813d58139fSopenharmony_ci/*
7823d58139fSopenharmony_ci * Decode width and qualifier in format
7833d58139fSopenharmony_ci */
7843d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec)
7853d58139fSopenharmony_ci{
7863d58139fSopenharmony_ci    const SecUnsignedChar *fmt = *format;
7873d58139fSopenharmony_ci    int finishFlag = 0;
7883d58139fSopenharmony_ci
7893d58139fSopenharmony_ci    do {
7903d58139fSopenharmony_ci        ++fmt; /*  First skip % , next  seek fmt */
7913d58139fSopenharmony_ci        /* May %*6d , so put it inside the loop */
7923d58139fSopenharmony_ci        if (SecDecodeScanWidth(&fmt, spec) != 0) {
7933d58139fSopenharmony_ci            return -1;
7943d58139fSopenharmony_ci        }
7953d58139fSopenharmony_ci        SecDecodeScanQualifier(&fmt, spec, &finishFlag);
7963d58139fSopenharmony_ci    } while (finishFlag == 0);
7973d58139fSopenharmony_ci    *format = fmt;
7983d58139fSopenharmony_ci    return 0;
7993d58139fSopenharmony_ci}
8003d58139fSopenharmony_ci
8013d58139fSopenharmony_ci/*
8023d58139fSopenharmony_ci * Judging whether a zeroing buffer is needed according to different formats
8033d58139fSopenharmony_ci */
8043d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeClearFormat(const SecUnsignedChar *format, int *convChr)
8053d58139fSopenharmony_ci{
8063d58139fSopenharmony_ci    const SecUnsignedChar *fmt = format;
8073d58139fSopenharmony_ci    /* To lowercase */
8083d58139fSopenharmony_ci    int ch = SECUREC_TO_LOWERCASE(*fmt);
8093d58139fSopenharmony_ci    if (!(ch == 'c' || ch == 's' || ch == SECUREC_BRACE)) {
8103d58139fSopenharmony_ci        return -1;     /* First argument is not a string type */
8113d58139fSopenharmony_ci    }
8123d58139fSopenharmony_ci    if (ch == SECUREC_BRACE) {
8133d58139fSopenharmony_ci#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
8143d58139fSopenharmony_ci        if (*fmt == SECUREC_CHAR('{')) {
8153d58139fSopenharmony_ci            return -1;
8163d58139fSopenharmony_ci        }
8173d58139fSopenharmony_ci#endif
8183d58139fSopenharmony_ci        ++fmt;
8193d58139fSopenharmony_ci        if (*fmt == SECUREC_CHAR('^')) {
8203d58139fSopenharmony_ci            ++fmt;
8213d58139fSopenharmony_ci        }
8223d58139fSopenharmony_ci        if (*fmt == SECUREC_CHAR(']')) {
8233d58139fSopenharmony_ci            ++fmt;
8243d58139fSopenharmony_ci        }
8253d58139fSopenharmony_ci        while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
8263d58139fSopenharmony_ci            ++fmt;
8273d58139fSopenharmony_ci        }
8283d58139fSopenharmony_ci        if (*fmt == SECUREC_CHAR('\0')) {
8293d58139fSopenharmony_ci            return -1; /* Trunc'd format string */
8303d58139fSopenharmony_ci        }
8313d58139fSopenharmony_ci    }
8323d58139fSopenharmony_ci    *convChr = ch;
8333d58139fSopenharmony_ci    return 0;
8343d58139fSopenharmony_ci}
8353d58139fSopenharmony_ci
8363d58139fSopenharmony_ci/*
8373d58139fSopenharmony_ci * Add L'\0' for wchar string , add '\0' for char string
8383d58139fSopenharmony_ci */
8393d58139fSopenharmony_ciSECUREC_INLINE void SecAddEndingZero(void *ptr, const SecScanSpec *spec)
8403d58139fSopenharmony_ci{
8413d58139fSopenharmony_ci    if (spec->suppress == 0) {
8423d58139fSopenharmony_ci        *(char *)ptr = '\0';
8433d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART
8443d58139fSopenharmony_ci        if (spec->isWCharOrLong > 0) {
8453d58139fSopenharmony_ci            *(wchar_t UNALIGNED *)ptr = L'\0';
8463d58139fSopenharmony_ci        }
8473d58139fSopenharmony_ci#endif
8483d58139fSopenharmony_ci    }
8493d58139fSopenharmony_ci}
8503d58139fSopenharmony_ci
8513d58139fSopenharmony_ciSECUREC_INLINE void SecDecodeClearArg(SecScanSpec *spec, va_list argList)
8523d58139fSopenharmony_ci{
8533d58139fSopenharmony_ci    va_list argListSave; /* Backup for argList value, this variable don't need initialized */
8543d58139fSopenharmony_ci    (void)SECUREC_MEMSET_FUNC_OPT(&argListSave, 0, sizeof(va_list)); /* To clear e530 argListSave not initialized */
8553d58139fSopenharmony_ci#if defined(va_copy)
8563d58139fSopenharmony_ci    va_copy(argListSave, argList);
8573d58139fSopenharmony_ci#elif defined(__va_copy)        /* For vxworks */
8583d58139fSopenharmony_ci    __va_copy(argListSave, argList);
8593d58139fSopenharmony_ci#else
8603d58139fSopenharmony_ci    argListSave = argList;
8613d58139fSopenharmony_ci#endif
8623d58139fSopenharmony_ci    spec->argPtr = (void *)va_arg(argListSave, void *);
8633d58139fSopenharmony_ci    /* Get the next argument, size of the array in characters */
8643d58139fSopenharmony_ci    /* Use 0xffffffffUL mask to Support  pass integer as array length */
8653d58139fSopenharmony_ci    spec->arrayWidth = ((size_t)(va_arg(argListSave, size_t))) & 0xffffffffUL;
8663d58139fSopenharmony_ci    va_end(argListSave);
8673d58139fSopenharmony_ci    /* To clear e438 last value assigned not used , the compiler will optimize this code */
8683d58139fSopenharmony_ci    (void)argListSave;
8693d58139fSopenharmony_ci}
8703d58139fSopenharmony_ci
8713d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
8723d58139fSopenharmony_ci/*
8733d58139fSopenharmony_ci *  Clean up the first %s %c buffer to zero for wchar version
8743d58139fSopenharmony_ci */
8753d58139fSopenharmony_civoid SecClearDestBufW(const wchar_t *buffer, const wchar_t *format, va_list argList)
8763d58139fSopenharmony_ci#else
8773d58139fSopenharmony_ci/*
8783d58139fSopenharmony_ci *  Clean up the first %s %c buffer to zero for char version
8793d58139fSopenharmony_ci */
8803d58139fSopenharmony_civoid SecClearDestBuf(const char *buffer, const char *format, va_list argList)
8813d58139fSopenharmony_ci#endif
8823d58139fSopenharmony_ci{
8833d58139fSopenharmony_ci    SecScanSpec spec;
8843d58139fSopenharmony_ci    int convChr = 0;
8853d58139fSopenharmony_ci    const SecUnsignedChar *fmt = (const SecUnsignedChar *)format;
8863d58139fSopenharmony_ci
8873d58139fSopenharmony_ci    /* Find first % */
8883d58139fSopenharmony_ci    while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR('%')) {
8893d58139fSopenharmony_ci        ++fmt;
8903d58139fSopenharmony_ci    }
8913d58139fSopenharmony_ci    if (*fmt == SECUREC_CHAR('\0')) {
8923d58139fSopenharmony_ci        return;
8933d58139fSopenharmony_ci    }
8943d58139fSopenharmony_ci
8953d58139fSopenharmony_ci    SecSetDefaultScanSpec(&spec);
8963d58139fSopenharmony_ci    if (SecDecodeScanFlag(&fmt, &spec) != 0) {
8973d58139fSopenharmony_ci        return;
8983d58139fSopenharmony_ci    }
8993d58139fSopenharmony_ci
9003d58139fSopenharmony_ci    /* Update wchar flag for %S %C */
9013d58139fSopenharmony_ci    SecUpdateWcharFlagByType(*fmt, &spec);
9023d58139fSopenharmony_ci    if (spec.suppress != 0) {
9033d58139fSopenharmony_ci        return;
9043d58139fSopenharmony_ci    }
9053d58139fSopenharmony_ci
9063d58139fSopenharmony_ci    if (SecDecodeClearFormat(fmt, &convChr) != 0) {
9073d58139fSopenharmony_ci        return;
9083d58139fSopenharmony_ci    }
9093d58139fSopenharmony_ci
9103d58139fSopenharmony_ci    if (*buffer != SECUREC_CHAR('\0') && convChr != 's') {
9113d58139fSopenharmony_ci        /*
9123d58139fSopenharmony_ci         * When buffer not empty just clear %s.
9133d58139fSopenharmony_ci         * Example call sscanf by  argment of (" \n", "%s", s, sizeof(s))
9143d58139fSopenharmony_ci         */
9153d58139fSopenharmony_ci        return;
9163d58139fSopenharmony_ci    }
9173d58139fSopenharmony_ci
9183d58139fSopenharmony_ci    SecDecodeClearArg(&spec, argList);
9193d58139fSopenharmony_ci    /* There is no need to judge the upper limit */
9203d58139fSopenharmony_ci    if (spec.arrayWidth == 0 || spec.argPtr == NULL) {
9213d58139fSopenharmony_ci        return;
9223d58139fSopenharmony_ci    }
9233d58139fSopenharmony_ci    /* Clear one char */
9243d58139fSopenharmony_ci    SecAddEndingZero(spec.argPtr, &spec);
9253d58139fSopenharmony_ci    return;
9263d58139fSopenharmony_ci}
9273d58139fSopenharmony_ci
9283d58139fSopenharmony_ci/*
9293d58139fSopenharmony_ci *  Assign number  to output buffer
9303d58139fSopenharmony_ci */
9313d58139fSopenharmony_ciSECUREC_INLINE void SecAssignNumber(const SecScanSpec *spec)
9323d58139fSopenharmony_ci{
9333d58139fSopenharmony_ci    void *argPtr = spec->argPtr;
9343d58139fSopenharmony_ci    if (spec->numberArgType != 0) {
9353d58139fSopenharmony_ci#if defined(SECUREC_VXWORKS_PLATFORM)
9363d58139fSopenharmony_ci#if defined(SECUREC_VXWORKS_PLATFORM_COMP)
9373d58139fSopenharmony_ci        *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64);
9383d58139fSopenharmony_ci#else
9393d58139fSopenharmony_ci        /* Take number64 as unsigned number unsigned to int clear Compile warning */
9403d58139fSopenharmony_ci        *(SecInt64 UNALIGNED *)argPtr = *(SecUnsignedInt64 *)(&(spec->number64));
9413d58139fSopenharmony_ci#endif
9423d58139fSopenharmony_ci#else
9433d58139fSopenharmony_ci        /* Take number64 as unsigned number */
9443d58139fSopenharmony_ci        *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64);
9453d58139fSopenharmony_ci#endif
9463d58139fSopenharmony_ci        return;
9473d58139fSopenharmony_ci    }
9483d58139fSopenharmony_ci    if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) {
9493d58139fSopenharmony_ci        /* Take number as unsigned number */
9503d58139fSopenharmony_ci        *(long UNALIGNED *)argPtr = (long)(spec->number);
9513d58139fSopenharmony_ci    } else if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
9523d58139fSopenharmony_ci        *(int UNALIGNED *)argPtr = (int)(spec->number);
9533d58139fSopenharmony_ci    } else if (spec->numberWidth == SECUREC_NUM_WIDTH_SHORT) {
9543d58139fSopenharmony_ci        /* Take number as unsigned number */
9553d58139fSopenharmony_ci        *(short UNALIGNED *)argPtr = (short)(spec->number);
9563d58139fSopenharmony_ci    } else {  /* < 0 for hh format modifier */
9573d58139fSopenharmony_ci        /* Take number as unsigned number */
9583d58139fSopenharmony_ci        *(char UNALIGNED *)argPtr = (char)(spec->number);
9593d58139fSopenharmony_ci    }
9603d58139fSopenharmony_ci}
9613d58139fSopenharmony_ci
9623d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
9633d58139fSopenharmony_ci/*
9643d58139fSopenharmony_ci *  Judge the long bit width
9653d58139fSopenharmony_ci */
9663d58139fSopenharmony_ciSECUREC_INLINE int SecIsLongBitEqual(int bitNum)
9673d58139fSopenharmony_ci{
9683d58139fSopenharmony_ci    return (int)((unsigned int)bitNum == SECUREC_LONG_BIT_NUM);
9693d58139fSopenharmony_ci}
9703d58139fSopenharmony_ci#endif
9713d58139fSopenharmony_ci
9723d58139fSopenharmony_ci/*
9733d58139fSopenharmony_ci * Convert hexadecimal characters to decimal value
9743d58139fSopenharmony_ci */
9753d58139fSopenharmony_ciSECUREC_INLINE int SecHexValueOfChar(SecInt ch)
9763d58139fSopenharmony_ci{
9773d58139fSopenharmony_ci    /* Use isdigit Causing tool false alarms */
9783d58139fSopenharmony_ci    return (int)((ch >= '0' && ch <= '9') ? ((unsigned char)ch - '0') :
9793d58139fSopenharmony_ci            ((((unsigned char)ch | (unsigned char)('a' - 'A')) - ('a')) + 10)); /* Adding 10 is to hex value */
9803d58139fSopenharmony_ci}
9813d58139fSopenharmony_ci
9823d58139fSopenharmony_ci/*
9833d58139fSopenharmony_ci * Parse decimal character to integer for 32bit .
9843d58139fSopenharmony_ci */
9853d58139fSopenharmony_cistatic void SecDecodeNumberDecimal(SecScanSpec *spec)
9863d58139fSopenharmony_ci{
9873d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
9883d58139fSopenharmony_ci    unsigned long decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN;
9893d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
9903d58139fSopenharmony_ci    if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
9913d58139fSopenharmony_ci        decimalEdge = (unsigned long)SECUREC_MAX_64BITS_VALUE_DIV_TEN;
9923d58139fSopenharmony_ci    }
9933d58139fSopenharmony_ci#endif
9943d58139fSopenharmony_ci    if (spec->number > decimalEdge) {
9953d58139fSopenharmony_ci        spec->beyondMax = 1;
9963d58139fSopenharmony_ci    }
9973d58139fSopenharmony_ci#endif
9983d58139fSopenharmony_ci    spec->number = SECUREC_MUL_TEN(spec->number);
9993d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
10003d58139fSopenharmony_ci    if (spec->number == SECUREC_MUL_TEN(decimalEdge)) {
10013d58139fSopenharmony_ci        /* This code is specially converted to unsigned long type for compatibility */
10023d58139fSopenharmony_ci        SecUnsignedInt64 number64As = (unsigned long)SECUREC_MAX_64BITS_VALUE - spec->number;
10033d58139fSopenharmony_ci        if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) {
10043d58139fSopenharmony_ci            spec->beyondMax = 1;
10053d58139fSopenharmony_ci        }
10063d58139fSopenharmony_ci    }
10073d58139fSopenharmony_ci#endif
10083d58139fSopenharmony_ci    spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
10093d58139fSopenharmony_ci}
10103d58139fSopenharmony_ci
10113d58139fSopenharmony_ci/*
10123d58139fSopenharmony_ci * Parse Hex character to integer for 32bit .
10133d58139fSopenharmony_ci */
10143d58139fSopenharmony_cistatic void SecDecodeNumberHex(SecScanSpec *spec)
10153d58139fSopenharmony_ci{
10163d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
10173d58139fSopenharmony_ci    if (SECUREC_LONG_HEX_BEYOND_MAX(spec->number)) {
10183d58139fSopenharmony_ci        spec->beyondMax = 1;
10193d58139fSopenharmony_ci    }
10203d58139fSopenharmony_ci#endif
10213d58139fSopenharmony_ci    spec->number = SECUREC_MUL_SIXTEEN(spec->number);
10223d58139fSopenharmony_ci    spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(spec->ch);
10233d58139fSopenharmony_ci}
10243d58139fSopenharmony_ci
10253d58139fSopenharmony_ci/*
10263d58139fSopenharmony_ci * Parse Octal character to integer for 32bit .
10273d58139fSopenharmony_ci */
10283d58139fSopenharmony_cistatic void SecDecodeNumberOctal(SecScanSpec *spec)
10293d58139fSopenharmony_ci{
10303d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
10313d58139fSopenharmony_ci    if (SECUREC_LONG_OCTAL_BEYOND_MAX(spec->number)) {
10323d58139fSopenharmony_ci        spec->beyondMax = 1;
10333d58139fSopenharmony_ci    }
10343d58139fSopenharmony_ci#endif
10353d58139fSopenharmony_ci    spec->number = SECUREC_MUL_EIGHT(spec->number);
10363d58139fSopenharmony_ci    spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
10373d58139fSopenharmony_ci}
10383d58139fSopenharmony_ci
10393d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
10403d58139fSopenharmony_ci/* Compatible with integer negative values other than int */
10413d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberNegativeOther(SecScanSpec *spec)
10423d58139fSopenharmony_ci{
10433d58139fSopenharmony_ci    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
10443d58139fSopenharmony_ci        if (spec->number > SECUREC_MIN_LONG_NEG_VALUE) {
10453d58139fSopenharmony_ci            spec->number = SECUREC_MIN_LONG_NEG_VALUE;
10463d58139fSopenharmony_ci        } else {
10473d58139fSopenharmony_ci            spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
10483d58139fSopenharmony_ci        }
10493d58139fSopenharmony_ci        if (spec->beyondMax != 0) {
10503d58139fSopenharmony_ci            if (spec->numberWidth < SECUREC_NUM_WIDTH_INT) {
10513d58139fSopenharmony_ci                spec->number = 0;
10523d58139fSopenharmony_ci            }
10533d58139fSopenharmony_ci            if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG) {
10543d58139fSopenharmony_ci                spec->number = SECUREC_MIN_LONG_NEG_VALUE;
10553d58139fSopenharmony_ci            }
10563d58139fSopenharmony_ci        }
10573d58139fSopenharmony_ci    } else { /* For o, u, x, X, p */
10583d58139fSopenharmony_ci        spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
10593d58139fSopenharmony_ci        if (spec->beyondMax != 0) {
10603d58139fSopenharmony_ci            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
10613d58139fSopenharmony_ci        }
10623d58139fSopenharmony_ci    }
10633d58139fSopenharmony_ci}
10643d58139fSopenharmony_ci/* Compatible processing of integer negative numbers */
10653d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberNegativeInt(SecScanSpec *spec)
10663d58139fSopenharmony_ci{
10673d58139fSopenharmony_ci    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
10683d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
10693d58139fSopenharmony_ci        if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
10703d58139fSopenharmony_ci            if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) {
10713d58139fSopenharmony_ci                spec->number = 0;
10723d58139fSopenharmony_ci            } else {
10733d58139fSopenharmony_ci                spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
10743d58139fSopenharmony_ci            }
10753d58139fSopenharmony_ci        }
10763d58139fSopenharmony_ci#else
10773d58139fSopenharmony_ci        if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
10783d58139fSopenharmony_ci            if ((spec->number > SECUREC_MIN_32BITS_NEG_VALUE)) {
10793d58139fSopenharmony_ci                spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
10803d58139fSopenharmony_ci            } else {
10813d58139fSopenharmony_ci                spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
10823d58139fSopenharmony_ci            }
10833d58139fSopenharmony_ci        }
10843d58139fSopenharmony_ci#endif
10853d58139fSopenharmony_ci        if (spec->beyondMax != 0) {
10863d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
10873d58139fSopenharmony_ci            if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
10883d58139fSopenharmony_ci                spec->number = 0;
10893d58139fSopenharmony_ci            }
10903d58139fSopenharmony_ci#else
10913d58139fSopenharmony_ci            if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
10923d58139fSopenharmony_ci                spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
10933d58139fSopenharmony_ci            }
10943d58139fSopenharmony_ci#endif
10953d58139fSopenharmony_ci        }
10963d58139fSopenharmony_ci    } else {            /* For o, u, x, X ,p */
10973d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
10983d58139fSopenharmony_ci        if (spec->number > SECUREC_MAX_32BITS_VALUE_INC) {
10993d58139fSopenharmony_ci            spec->number = SECUREC_MAX_32BITS_VALUE;
11003d58139fSopenharmony_ci        } else {
11013d58139fSopenharmony_ci            spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
11023d58139fSopenharmony_ci        }
11033d58139fSopenharmony_ci#else
11043d58139fSopenharmony_ci        spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
11053d58139fSopenharmony_ci#endif
11063d58139fSopenharmony_ci        if (spec->beyondMax != 0) {
11073d58139fSopenharmony_ci            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
11083d58139fSopenharmony_ci        }
11093d58139fSopenharmony_ci    }
11103d58139fSopenharmony_ci}
11113d58139fSopenharmony_ci
11123d58139fSopenharmony_ci/* Compatible with integer positive values other than int */
11133d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberPositiveOther(SecScanSpec *spec)
11143d58139fSopenharmony_ci{
11153d58139fSopenharmony_ci    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
11163d58139fSopenharmony_ci        if (spec->number > SECUREC_MAX_LONG_POS_VALUE) {
11173d58139fSopenharmony_ci            spec->number = SECUREC_MAX_LONG_POS_VALUE;
11183d58139fSopenharmony_ci        }
11193d58139fSopenharmony_ci        if ((spec->beyondMax != 0 && spec->numberWidth < SECUREC_NUM_WIDTH_INT)) {
11203d58139fSopenharmony_ci            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
11213d58139fSopenharmony_ci        }
11223d58139fSopenharmony_ci        if (spec->beyondMax != 0 && spec->numberWidth == SECUREC_NUM_WIDTH_LONG) {
11233d58139fSopenharmony_ci            spec->number = SECUREC_MAX_LONG_POS_VALUE;
11243d58139fSopenharmony_ci        }
11253d58139fSopenharmony_ci    } else {
11263d58139fSopenharmony_ci        if (spec->beyondMax != 0) {
11273d58139fSopenharmony_ci            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
11283d58139fSopenharmony_ci        }
11293d58139fSopenharmony_ci    }
11303d58139fSopenharmony_ci}
11313d58139fSopenharmony_ci
11323d58139fSopenharmony_ci/* Compatible processing of integer positive numbers */
11333d58139fSopenharmony_ciSECUREC_INLINE void SecFinishNumberPositiveInt(SecScanSpec *spec)
11343d58139fSopenharmony_ci{
11353d58139fSopenharmony_ci    if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
11363d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
11373d58139fSopenharmony_ci        if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
11383d58139fSopenharmony_ci            if (spec->number > SECUREC_MAX_64BITS_POS_VALUE) {
11393d58139fSopenharmony_ci                spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
11403d58139fSopenharmony_ci            }
11413d58139fSopenharmony_ci        }
11423d58139fSopenharmony_ci        if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
11433d58139fSopenharmony_ci            spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
11443d58139fSopenharmony_ci        }
11453d58139fSopenharmony_ci#else
11463d58139fSopenharmony_ci        if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
11473d58139fSopenharmony_ci            if (spec->number > SECUREC_MAX_32BITS_POS_VALUE) {
11483d58139fSopenharmony_ci                spec->number = SECUREC_MAX_32BITS_POS_VALUE;
11493d58139fSopenharmony_ci            }
11503d58139fSopenharmony_ci        }
11513d58139fSopenharmony_ci        if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
11523d58139fSopenharmony_ci            spec->number = SECUREC_MAX_32BITS_POS_VALUE;
11533d58139fSopenharmony_ci        }
11543d58139fSopenharmony_ci#endif
11553d58139fSopenharmony_ci    } else {            /* For o,u,x,X,p */
11563d58139fSopenharmony_ci        if (spec->beyondMax != 0) {
11573d58139fSopenharmony_ci            spec->number = SECUREC_MAX_32BITS_VALUE;
11583d58139fSopenharmony_ci        }
11593d58139fSopenharmony_ci    }
11603d58139fSopenharmony_ci}
11613d58139fSopenharmony_ci
11623d58139fSopenharmony_ci#endif
11633d58139fSopenharmony_ci
11643d58139fSopenharmony_ci/*
11653d58139fSopenharmony_ci * Parse decimal character to integer for 64bit .
11663d58139fSopenharmony_ci */
11673d58139fSopenharmony_cistatic void SecDecodeNumber64Decimal(SecScanSpec *spec)
11683d58139fSopenharmony_ci{
11693d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
11703d58139fSopenharmony_ci    if (spec->number64 > SECUREC_MAX_64BITS_VALUE_DIV_TEN) {
11713d58139fSopenharmony_ci        spec->beyondMax = 1;
11723d58139fSopenharmony_ci    }
11733d58139fSopenharmony_ci#endif
11743d58139fSopenharmony_ci    spec->number64 = SECUREC_MUL_TEN(spec->number64);
11753d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
11763d58139fSopenharmony_ci    if (spec->number64 == SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT) {
11773d58139fSopenharmony_ci        SecUnsignedInt64 number64As = (SecUnsignedInt64)SECUREC_MAX_64BITS_VALUE - spec->number64;
11783d58139fSopenharmony_ci        if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) {
11793d58139fSopenharmony_ci            spec->beyondMax = 1;
11803d58139fSopenharmony_ci        }
11813d58139fSopenharmony_ci    }
11823d58139fSopenharmony_ci#endif
11833d58139fSopenharmony_ci    spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
11843d58139fSopenharmony_ci}
11853d58139fSopenharmony_ci
11863d58139fSopenharmony_ci/*
11873d58139fSopenharmony_ci * Parse Hex character to integer for 64bit .
11883d58139fSopenharmony_ci */
11893d58139fSopenharmony_cistatic void SecDecodeNumber64Hex(SecScanSpec *spec)
11903d58139fSopenharmony_ci{
11913d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
11923d58139fSopenharmony_ci    if (SECUREC_QWORD_HEX_BEYOND_MAX(spec->number64)) {
11933d58139fSopenharmony_ci        spec->beyondMax = 1;
11943d58139fSopenharmony_ci    }
11953d58139fSopenharmony_ci#endif
11963d58139fSopenharmony_ci    spec->number64 = SECUREC_MUL_SIXTEEN(spec->number64);
11973d58139fSopenharmony_ci    spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(spec->ch);
11983d58139fSopenharmony_ci}
11993d58139fSopenharmony_ci
12003d58139fSopenharmony_ci/*
12013d58139fSopenharmony_ci * Parse Octal character to integer for 64bit .
12023d58139fSopenharmony_ci */
12033d58139fSopenharmony_cistatic void SecDecodeNumber64Octal(SecScanSpec *spec)
12043d58139fSopenharmony_ci{
12053d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
12063d58139fSopenharmony_ci    if (SECUREC_QWORD_OCTAL_BEYOND_MAX(spec->number64)) {
12073d58139fSopenharmony_ci        spec->beyondMax = 1;
12083d58139fSopenharmony_ci    }
12093d58139fSopenharmony_ci#endif
12103d58139fSopenharmony_ci    spec->number64 = SECUREC_MUL_EIGHT(spec->number64);
12113d58139fSopenharmony_ci    spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0'));
12123d58139fSopenharmony_ci}
12133d58139fSopenharmony_ci
12143d58139fSopenharmony_ci#define SECUREC_DECODE_NUMBER_FUNC_NUM 2
12153d58139fSopenharmony_ci
12163d58139fSopenharmony_ci/*
12173d58139fSopenharmony_ci * Parse 64-bit integer formatted input, return 0 when ch is a number.
12183d58139fSopenharmony_ci */
12193d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeNumber(SecScanSpec *spec)
12203d58139fSopenharmony_ci{
12213d58139fSopenharmony_ci    /* Function name cannot add address symbol, causing 546 alarm */
12223d58139fSopenharmony_ci    static void (* const secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
12233d58139fSopenharmony_ci        SecDecodeNumberHex, SecDecodeNumber64Hex
12243d58139fSopenharmony_ci    };
12253d58139fSopenharmony_ci    static void (* const secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
12263d58139fSopenharmony_ci        SecDecodeNumberOctal, SecDecodeNumber64Octal
12273d58139fSopenharmony_ci    };
12283d58139fSopenharmony_ci    static void (* const secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
12293d58139fSopenharmony_ci        SecDecodeNumberDecimal, SecDecodeNumber64Decimal
12303d58139fSopenharmony_ci    };
12313d58139fSopenharmony_ci    if (spec->convChr == 'x' || spec->convChr == 'p') {
12323d58139fSopenharmony_ci        if (SecIsXdigit(spec->ch) != 0) {
12333d58139fSopenharmony_ci            (*secDecodeNumberHex[spec->numberArgType])(spec);
12343d58139fSopenharmony_ci        } else {
12353d58139fSopenharmony_ci            return -1;
12363d58139fSopenharmony_ci        }
12373d58139fSopenharmony_ci        return 0;
12383d58139fSopenharmony_ci    }
12393d58139fSopenharmony_ci    if (SecIsDigit(spec->ch) == 0) {
12403d58139fSopenharmony_ci        return -1;
12413d58139fSopenharmony_ci    }
12423d58139fSopenharmony_ci    if (spec->convChr == 'o') {
12433d58139fSopenharmony_ci        if (spec->ch < SECUREC_CHAR('8')) { /* Octal maximum limit '8' */
12443d58139fSopenharmony_ci            (*secDecodeNumberOctal[spec->numberArgType])(spec);
12453d58139fSopenharmony_ci        } else {
12463d58139fSopenharmony_ci            return -1;
12473d58139fSopenharmony_ci        }
12483d58139fSopenharmony_ci    } else { /* The convChr is 'd' */
12493d58139fSopenharmony_ci        (*secDecodeNumberDecimal[spec->numberArgType])(spec);
12503d58139fSopenharmony_ci    }
12513d58139fSopenharmony_ci    return 0;
12523d58139fSopenharmony_ci}
12533d58139fSopenharmony_ci
12543d58139fSopenharmony_ci/*
12553d58139fSopenharmony_ci * Complete the final 32-bit integer formatted input
12563d58139fSopenharmony_ci */
12573d58139fSopenharmony_cistatic void SecFinishNumber(SecScanSpec *spec)
12583d58139fSopenharmony_ci{
12593d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
12603d58139fSopenharmony_ci    if (spec->negative != 0) {
12613d58139fSopenharmony_ci        if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
12623d58139fSopenharmony_ci            SecFinishNumberNegativeInt(spec);
12633d58139fSopenharmony_ci        } else {
12643d58139fSopenharmony_ci            SecFinishNumberNegativeOther(spec);
12653d58139fSopenharmony_ci        }
12663d58139fSopenharmony_ci    } else {
12673d58139fSopenharmony_ci        if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
12683d58139fSopenharmony_ci            SecFinishNumberPositiveInt(spec);
12693d58139fSopenharmony_ci        } else {
12703d58139fSopenharmony_ci            SecFinishNumberPositiveOther(spec);
12713d58139fSopenharmony_ci        }
12723d58139fSopenharmony_ci    }
12733d58139fSopenharmony_ci#else
12743d58139fSopenharmony_ci    if (spec->negative != 0) {
12753d58139fSopenharmony_ci#if defined(__hpux)
12763d58139fSopenharmony_ci        if (spec->oriConvChr != 'p') {
12773d58139fSopenharmony_ci            spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
12783d58139fSopenharmony_ci        }
12793d58139fSopenharmony_ci#else
12803d58139fSopenharmony_ci        spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
12813d58139fSopenharmony_ci#endif
12823d58139fSopenharmony_ci    }
12833d58139fSopenharmony_ci#endif
12843d58139fSopenharmony_ci    return;
12853d58139fSopenharmony_ci}
12863d58139fSopenharmony_ci
12873d58139fSopenharmony_ci/*
12883d58139fSopenharmony_ci * Complete the final 64-bit integer formatted input
12893d58139fSopenharmony_ci */
12903d58139fSopenharmony_cistatic void SecFinishNumber64(SecScanSpec *spec)
12913d58139fSopenharmony_ci{
12923d58139fSopenharmony_ci#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
12933d58139fSopenharmony_ci    if (spec->negative != 0) {
12943d58139fSopenharmony_ci        if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
12953d58139fSopenharmony_ci            if (spec->number64 > SECUREC_MIN_64BITS_NEG_VALUE) {
12963d58139fSopenharmony_ci                spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
12973d58139fSopenharmony_ci            } else {
12983d58139fSopenharmony_ci                spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
12993d58139fSopenharmony_ci            }
13003d58139fSopenharmony_ci            if (spec->beyondMax != 0) {
13013d58139fSopenharmony_ci                spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
13023d58139fSopenharmony_ci            }
13033d58139fSopenharmony_ci        } else {                /* For o, u, x, X, p */
13043d58139fSopenharmony_ci            spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
13053d58139fSopenharmony_ci            if (spec->beyondMax != 0) {
13063d58139fSopenharmony_ci                spec->number64 = SECUREC_MAX_64BITS_VALUE;
13073d58139fSopenharmony_ci            }
13083d58139fSopenharmony_ci        }
13093d58139fSopenharmony_ci    } else {
13103d58139fSopenharmony_ci        if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
13113d58139fSopenharmony_ci            if (spec->number64 > SECUREC_MAX_64BITS_POS_VALUE) {
13123d58139fSopenharmony_ci                spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
13133d58139fSopenharmony_ci            }
13143d58139fSopenharmony_ci            if (spec->beyondMax != 0) {
13153d58139fSopenharmony_ci                spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
13163d58139fSopenharmony_ci            }
13173d58139fSopenharmony_ci        } else {
13183d58139fSopenharmony_ci            if (spec->beyondMax != 0) {
13193d58139fSopenharmony_ci                spec->number64 = SECUREC_MAX_64BITS_VALUE;
13203d58139fSopenharmony_ci            }
13213d58139fSopenharmony_ci        }
13223d58139fSopenharmony_ci    }
13233d58139fSopenharmony_ci#else
13243d58139fSopenharmony_ci    if (spec->negative != 0) {
13253d58139fSopenharmony_ci#if defined(__hpux)
13263d58139fSopenharmony_ci        if (spec->oriConvChr != 'p') {
13273d58139fSopenharmony_ci            spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
13283d58139fSopenharmony_ci        }
13293d58139fSopenharmony_ci#else
13303d58139fSopenharmony_ci        spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
13313d58139fSopenharmony_ci#endif
13323d58139fSopenharmony_ci    }
13333d58139fSopenharmony_ci#endif
13343d58139fSopenharmony_ci    return;
13353d58139fSopenharmony_ci}
13363d58139fSopenharmony_ci
13373d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE
13383d58139fSopenharmony_ci
13393d58139fSopenharmony_ci/*
13403d58139fSopenharmony_ci *  Adjust the pointer position of the file stream
13413d58139fSopenharmony_ci */
13423d58139fSopenharmony_ciSECUREC_INLINE void SecSeekStream(SecFileStream *stream)
13433d58139fSopenharmony_ci{
13443d58139fSopenharmony_ci    if (stream->count == 0) {
13453d58139fSopenharmony_ci        if (feof(stream->pf) != 0) {
13463d58139fSopenharmony_ci            /* File pointer at the end of file, don't need to seek back */
13473d58139fSopenharmony_ci            stream->base[0] = '\0';
13483d58139fSopenharmony_ci            return;
13493d58139fSopenharmony_ci        }
13503d58139fSopenharmony_ci    }
13513d58139fSopenharmony_ci    /* Seek to original position, for file read, but nothing to input */
13523d58139fSopenharmony_ci    if (fseek(stream->pf, stream->oriFilePos, SEEK_SET) != 0) {
13533d58139fSopenharmony_ci        /* Seek failed, ignore it */
13543d58139fSopenharmony_ci        stream->oriFilePos = 0;
13553d58139fSopenharmony_ci        return;
13563d58139fSopenharmony_ci    }
13573d58139fSopenharmony_ci
13583d58139fSopenharmony_ci    if (stream->fileRealRead > 0) { /* Do not seek without input data */
13593d58139fSopenharmony_ci#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
13603d58139fSopenharmony_ci        size_t residue = stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE;
13613d58139fSopenharmony_ci        size_t loops;
13623d58139fSopenharmony_ci        for (loops = 0; loops < (stream->fileRealRead / SECUREC_BUFFERED_BLOK_SIZE); ++loops) {
13633d58139fSopenharmony_ci            if (fread(stream->base, (size_t)SECUREC_BUFFERED_BLOK_SIZE, (size_t)1, stream->pf) != (size_t)1) {
13643d58139fSopenharmony_ci                break;
13653d58139fSopenharmony_ci            }
13663d58139fSopenharmony_ci        }
13673d58139fSopenharmony_ci        if (residue != 0) {
13683d58139fSopenharmony_ci            long curFilePos;
13693d58139fSopenharmony_ci            if (fread(stream->base, residue, (size_t)1, stream->pf) != (size_t)1) {
13703d58139fSopenharmony_ci                return;
13713d58139fSopenharmony_ci            }
13723d58139fSopenharmony_ci            curFilePos = ftell(stream->pf);
13733d58139fSopenharmony_ci            if (curFilePos < stream->oriFilePos ||
13743d58139fSopenharmony_ci                (size_t)(unsigned long)(curFilePos - stream->oriFilePos) < stream->fileRealRead) {
13753d58139fSopenharmony_ci                /* Try to remedy the problem */
13763d58139fSopenharmony_ci                long adjustNum = (long)(stream->fileRealRead - (size_t)(unsigned long)(curFilePos - stream->oriFilePos));
13773d58139fSopenharmony_ci                (void)fseek(stream->pf, adjustNum, SEEK_CUR);
13783d58139fSopenharmony_ci            }
13793d58139fSopenharmony_ci        }
13803d58139fSopenharmony_ci#else
13813d58139fSopenharmony_ci        /* Seek from oriFilePos. Regardless of the integer sign problem, call scanf will not read very large data */
13823d58139fSopenharmony_ci        if (fseek(stream->pf, (long)stream->fileRealRead, SEEK_CUR) != 0) {
13833d58139fSopenharmony_ci            /* Seek failed, ignore it */
13843d58139fSopenharmony_ci            stream->oriFilePos = 0;
13853d58139fSopenharmony_ci            return;
13863d58139fSopenharmony_ci        }
13873d58139fSopenharmony_ci#endif
13883d58139fSopenharmony_ci    }
13893d58139fSopenharmony_ci    return;
13903d58139fSopenharmony_ci}
13913d58139fSopenharmony_ci
13923d58139fSopenharmony_ci/*
13933d58139fSopenharmony_ci *  Adjust the pointer position of the file stream and free memory
13943d58139fSopenharmony_ci */
13953d58139fSopenharmony_ciSECUREC_INLINE void SecAdjustStream(SecFileStream *stream)
13963d58139fSopenharmony_ci{
13973d58139fSopenharmony_ci    if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0 && stream->base != NULL) {
13983d58139fSopenharmony_ci        SecSeekStream(stream);
13993d58139fSopenharmony_ci        SECUREC_FREE(stream->base);
14003d58139fSopenharmony_ci        stream->base = NULL;
14013d58139fSopenharmony_ci    }
14023d58139fSopenharmony_ci    return;
14033d58139fSopenharmony_ci}
14043d58139fSopenharmony_ci#endif
14053d58139fSopenharmony_ci
14063d58139fSopenharmony_ciSECUREC_INLINE void SecSkipSpaceFormat(const SecUnsignedChar **format)
14073d58139fSopenharmony_ci{
14083d58139fSopenharmony_ci    const SecUnsignedChar *fmt = *format;
14093d58139fSopenharmony_ci    while (SecIsSpace((SecInt)(int)(*fmt)) != 0) {
14103d58139fSopenharmony_ci        ++fmt;
14113d58139fSopenharmony_ci    }
14123d58139fSopenharmony_ci    *format = fmt;
14133d58139fSopenharmony_ci}
14143d58139fSopenharmony_ci
14153d58139fSopenharmony_ci#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)
14163d58139fSopenharmony_ci/*
14173d58139fSopenharmony_ci * Handling multi-character characters
14183d58139fSopenharmony_ci */
14193d58139fSopenharmony_ciSECUREC_INLINE int SecDecodeLeadByte(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream)
14203d58139fSopenharmony_ci{
14213d58139fSopenharmony_ci#if SECUREC_HAVE_MBTOWC
14223d58139fSopenharmony_ci    const SecUnsignedChar *fmt = *format;
14233d58139fSopenharmony_ci    int ch1 = (int)spec->ch;
14243d58139fSopenharmony_ci    int ch2 = SecGetChar(stream, &(spec->charCount));
14253d58139fSopenharmony_ci    spec->ch = (SecInt)ch2;
14263d58139fSopenharmony_ci    if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch2) {
14273d58139fSopenharmony_ci        /* in console mode, ungetc twice may cause problem */
14283d58139fSopenharmony_ci        SecUnGetChar(ch2, stream, &(spec->charCount));
14293d58139fSopenharmony_ci        SecUnGetChar(ch1, stream, &(spec->charCount));
14303d58139fSopenharmony_ci        return -1;
14313d58139fSopenharmony_ci    }
14323d58139fSopenharmony_ci    ++fmt;
14333d58139fSopenharmony_ci    if ((unsigned int)MB_CUR_MAX >= SECUREC_UTF8_BOM_HEADER_SIZE &&
14343d58139fSopenharmony_ci        (((unsigned char)ch1 & SECUREC_UTF8_LEAD_1ST) == SECUREC_UTF8_LEAD_1ST) &&
14353d58139fSopenharmony_ci        (((unsigned char)ch2 & SECUREC_UTF8_LEAD_2ND) == SECUREC_UTF8_LEAD_2ND)) {
14363d58139fSopenharmony_ci        /* This char is very likely to be a UTF-8 char */
14373d58139fSopenharmony_ci        wchar_t tempWChar;
14383d58139fSopenharmony_ci        char temp[SECUREC_MULTI_BYTE_MAX_LEN];
14393d58139fSopenharmony_ci        int ch3 = (int)SecGetChar(stream, &(spec->charCount));
14403d58139fSopenharmony_ci        spec->ch = (SecInt)ch3;
14413d58139fSopenharmony_ci        if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch3) {
14423d58139fSopenharmony_ci            SecUnGetChar(ch3, stream, &(spec->charCount));
14433d58139fSopenharmony_ci            return -1;
14443d58139fSopenharmony_ci        }
14453d58139fSopenharmony_ci        temp[0] = (char)ch1;
14463d58139fSopenharmony_ci        temp[1] = (char)ch2; /* 1 index of second character */
14473d58139fSopenharmony_ci        temp[2] = (char)ch3; /* 2 index of third character */
14483d58139fSopenharmony_ci        temp[3] = '\0';      /* 3 of string terminator position */
14493d58139fSopenharmony_ci        if (mbtowc(&tempWChar, temp, sizeof(temp)) > 0) {
14503d58139fSopenharmony_ci            /* Succeed */
14513d58139fSopenharmony_ci            ++fmt;
14523d58139fSopenharmony_ci            --spec->charCount;
14533d58139fSopenharmony_ci        } else {
14543d58139fSopenharmony_ci            SecUnGetChar(ch3, stream, &(spec->charCount));
14553d58139fSopenharmony_ci        }
14563d58139fSopenharmony_ci    }
14573d58139fSopenharmony_ci    --spec->charCount;    /* Only count as one character read */
14583d58139fSopenharmony_ci    *format = fmt;
14593d58139fSopenharmony_ci    return 0;
14603d58139fSopenharmony_ci#else
14613d58139fSopenharmony_ci    SecUnGetChar(spec->ch, stream, &(spec->charCount));
14623d58139fSopenharmony_ci    (void)format; /* To clear e438 last value assigned not used , the compiler will optimize this code */
14633d58139fSopenharmony_ci    return -1;
14643d58139fSopenharmony_ci#endif
14653d58139fSopenharmony_ci}
14663d58139fSopenharmony_ci
14673d58139fSopenharmony_ciSECUREC_INLINE int SecFilterWcharInFormat(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream)
14683d58139fSopenharmony_ci{
14693d58139fSopenharmony_ci    if (SecIsLeadByte(spec->ch) != 0) {
14703d58139fSopenharmony_ci        if (SecDecodeLeadByte(spec, format, stream) != 0) {
14713d58139fSopenharmony_ci            return -1;
14723d58139fSopenharmony_ci        }
14733d58139fSopenharmony_ci    }
14743d58139fSopenharmony_ci    return 0;
14753d58139fSopenharmony_ci}
14763d58139fSopenharmony_ci#endif
14773d58139fSopenharmony_ci
14783d58139fSopenharmony_ci/*
14793d58139fSopenharmony_ci *  Resolving sequence of characters from %[ format, format wile point to ']'
14803d58139fSopenharmony_ci */
14813d58139fSopenharmony_ciSECUREC_INLINE int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable)
14823d58139fSopenharmony_ci{
14833d58139fSopenharmony_ci    const SecUnsignedChar *fmt = *format;
14843d58139fSopenharmony_ci    SecUnsignedChar prevChar = 0;
14853d58139fSopenharmony_ci#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
14863d58139fSopenharmony_ci    if (*fmt == SECUREC_CHAR('{')) {
14873d58139fSopenharmony_ci        return -1;
14883d58139fSopenharmony_ci    }
14893d58139fSopenharmony_ci#endif
14903d58139fSopenharmony_ci    /* For building "table" data */
14913d58139fSopenharmony_ci    ++fmt; /* Skip [ */
14923d58139fSopenharmony_ci    bracketTable->mask = 0; /* Set all bits to 0 */
14933d58139fSopenharmony_ci    if (*fmt == SECUREC_CHAR('^')) {
14943d58139fSopenharmony_ci        ++fmt;
14953d58139fSopenharmony_ci        bracketTable->mask = (unsigned char)0xffU; /* Use 0xffU to set all bits to 1 */
14963d58139fSopenharmony_ci    }
14973d58139fSopenharmony_ci    if (*fmt == SECUREC_CHAR(']')) {
14983d58139fSopenharmony_ci        prevChar = SECUREC_CHAR(']');
14993d58139fSopenharmony_ci        ++fmt;
15003d58139fSopenharmony_ci        SecBracketSetBit(bracketTable->table, SECUREC_CHAR(']'));
15013d58139fSopenharmony_ci    }
15023d58139fSopenharmony_ci    while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
15033d58139fSopenharmony_ci        SecUnsignedChar expCh = *fmt;
15043d58139fSopenharmony_ci        ++fmt;
15053d58139fSopenharmony_ci        if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) {
15063d58139fSopenharmony_ci            /* Normal character */
15073d58139fSopenharmony_ci            prevChar = expCh;
15083d58139fSopenharmony_ci            SecBracketSetBit(bracketTable->table, expCh);
15093d58139fSopenharmony_ci        } else {
15103d58139fSopenharmony_ci            /* For %[a-z] */
15113d58139fSopenharmony_ci            expCh = *fmt;   /* Get end of range */
15123d58139fSopenharmony_ci            ++fmt;
15133d58139fSopenharmony_ci            if (prevChar <= expCh) {  /* %[a-z] %[a-a] */
15143d58139fSopenharmony_ci                SecBracketSetBitRange(bracketTable->table, prevChar, expCh);
15153d58139fSopenharmony_ci            } else {
15163d58139fSopenharmony_ci                /* For %[z-a] */
15173d58139fSopenharmony_ci#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
15183d58139fSopenharmony_ci                /* Swap start and end characters */
15193d58139fSopenharmony_ci                SecBracketSetBitRange(bracketTable->table, expCh, prevChar);
15203d58139fSopenharmony_ci#else
15213d58139fSopenharmony_ci                SecBracketSetBit(bracketTable->table, SECUREC_CHAR('-'));
15223d58139fSopenharmony_ci                SecBracketSetBit(bracketTable->table, expCh);
15233d58139fSopenharmony_ci#endif
15243d58139fSopenharmony_ci            }
15253d58139fSopenharmony_ci            prevChar = 0;
15263d58139fSopenharmony_ci        }
15273d58139fSopenharmony_ci    }
15283d58139fSopenharmony_ci    *format = fmt;
15293d58139fSopenharmony_ci    return 0;
15303d58139fSopenharmony_ci}
15313d58139fSopenharmony_ci
15323d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
15333d58139fSopenharmony_ciSECUREC_INLINE int SecInputForWchar(SecScanSpec *spec)
15343d58139fSopenharmony_ci{
15353d58139fSopenharmony_ci    void *endPtr = spec->argPtr;
15363d58139fSopenharmony_ci    if (spec->isWCharOrLong > 0) {
15373d58139fSopenharmony_ci        *(wchar_t UNALIGNED *)endPtr = (wchar_t)spec->ch;
15383d58139fSopenharmony_ci        endPtr = (wchar_t *)endPtr + 1;
15393d58139fSopenharmony_ci        --spec->arrayWidth;
15403d58139fSopenharmony_ci    } else {
15413d58139fSopenharmony_ci#if SECUREC_HAVE_WCTOMB
15423d58139fSopenharmony_ci        int temp;
15433d58139fSopenharmony_ci        char tmpBuf[SECUREC_MB_LEN + 1];
15443d58139fSopenharmony_ci        SECUREC_MASK_MSVC_CRT_WARNING temp = wctomb(tmpBuf, (wchar_t)spec->ch);
15453d58139fSopenharmony_ci        SECUREC_END_MASK_MSVC_CRT_WARNING
15463d58139fSopenharmony_ci        if (temp <= 0 || (size_t)(unsigned int)temp > sizeof(tmpBuf)) {
15473d58139fSopenharmony_ci            /* If wctomb  error, then ignore character */
15483d58139fSopenharmony_ci            return 0;
15493d58139fSopenharmony_ci        }
15503d58139fSopenharmony_ci        if (((size_t)(unsigned int)temp) > spec->arrayWidth) {
15513d58139fSopenharmony_ci            return -1;
15523d58139fSopenharmony_ci        }
15533d58139fSopenharmony_ci        if (memcpy_s(endPtr, spec->arrayWidth, tmpBuf, (size_t)(unsigned int)temp) != EOK) {
15543d58139fSopenharmony_ci            return -1;
15553d58139fSopenharmony_ci        }
15563d58139fSopenharmony_ci        endPtr = (char *)endPtr + temp;
15573d58139fSopenharmony_ci        spec->arrayWidth -= (size_t)(unsigned int)temp;
15583d58139fSopenharmony_ci#else
15593d58139fSopenharmony_ci        return -1;
15603d58139fSopenharmony_ci#endif
15613d58139fSopenharmony_ci    }
15623d58139fSopenharmony_ci    spec->argPtr = endPtr;
15633d58139fSopenharmony_ci    return 0;
15643d58139fSopenharmony_ci}
15653d58139fSopenharmony_ci#endif
15663d58139fSopenharmony_ci
15673d58139fSopenharmony_ci#ifndef SECUREC_FOR_WCHAR
15683d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART
15693d58139fSopenharmony_ciSECUREC_INLINE wchar_t SecConvertInputCharToWchar(SecScanSpec *spec, SecFileStream *stream)
15703d58139fSopenharmony_ci{
15713d58139fSopenharmony_ci    wchar_t tempWChar = L'?';   /* Set default char is ? */
15723d58139fSopenharmony_ci#if SECUREC_HAVE_MBTOWC
15733d58139fSopenharmony_ci    char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1];
15743d58139fSopenharmony_ci    temp[0] = (char)spec->ch;
15753d58139fSopenharmony_ci    temp[1] = '\0';
15763d58139fSopenharmony_ci#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
15773d58139fSopenharmony_ci    if (SecIsLeadByte(spec->ch) != 0) {
15783d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount));
15793d58139fSopenharmony_ci        temp[1] = (char)spec->ch;
15803d58139fSopenharmony_ci        temp[2] = '\0'; /* 2 of string terminator position */
15813d58139fSopenharmony_ci    }
15823d58139fSopenharmony_ci    if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) {
15833d58139fSopenharmony_ci        /* No string termination error for tool */
15843d58139fSopenharmony_ci        tempWChar = L'?';
15853d58139fSopenharmony_ci    }
15863d58139fSopenharmony_ci#else
15873d58139fSopenharmony_ci    if (SecIsLeadByte(spec->ch) != 0) {
15883d58139fSopenharmony_ci        int convRes = 0;
15893d58139fSopenharmony_ci        int di = 1;
15903d58139fSopenharmony_ci        /* On Linux like system, the string is encoded in UTF-8 */
15913d58139fSopenharmony_ci        while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) {
15923d58139fSopenharmony_ci            spec->ch = SecGetChar(stream, &(spec->charCount));
15933d58139fSopenharmony_ci            temp[di] = (char)spec->ch;
15943d58139fSopenharmony_ci            ++di;
15953d58139fSopenharmony_ci            temp[di] = '\0';
15963d58139fSopenharmony_ci            convRes = mbtowc(&tempWChar, temp, sizeof(temp));
15973d58139fSopenharmony_ci        }
15983d58139fSopenharmony_ci        if (convRes <= 0) {
15993d58139fSopenharmony_ci            tempWChar = L'?';
16003d58139fSopenharmony_ci        }
16013d58139fSopenharmony_ci    } else {
16023d58139fSopenharmony_ci        if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) {
16033d58139fSopenharmony_ci            tempWChar = L'?';
16043d58139fSopenharmony_ci        }
16053d58139fSopenharmony_ci    }
16063d58139fSopenharmony_ci#endif
16073d58139fSopenharmony_ci#else
16083d58139fSopenharmony_ci    (void)spec;      /* To clear e438 last value assigned not used , the compiler will optimize this code */
16093d58139fSopenharmony_ci    (void)stream;    /* To clear e438 last value assigned not used , the compiler will optimize this code */
16103d58139fSopenharmony_ci#endif /* SECUREC_HAVE_MBTOWC */
16113d58139fSopenharmony_ci
16123d58139fSopenharmony_ci    return tempWChar;
16133d58139fSopenharmony_ci}
16143d58139fSopenharmony_ci#endif /* SECUREC_HAVE_WCHART */
16153d58139fSopenharmony_ci
16163d58139fSopenharmony_ciSECUREC_INLINE int SecInputForChar(SecScanSpec *spec, SecFileStream *stream)
16173d58139fSopenharmony_ci{
16183d58139fSopenharmony_ci    void *endPtr = spec->argPtr;
16193d58139fSopenharmony_ci    if (spec->isWCharOrLong > 0) {
16203d58139fSopenharmony_ci#if SECUREC_HAVE_WCHART
16213d58139fSopenharmony_ci        *(wchar_t UNALIGNED *)endPtr = SecConvertInputCharToWchar(spec, stream);
16223d58139fSopenharmony_ci        endPtr = (wchar_t *)endPtr + 1;
16233d58139fSopenharmony_ci        --spec->arrayWidth;
16243d58139fSopenharmony_ci#else
16253d58139fSopenharmony_ci    (void)stream;    /* To clear e438 last value assigned not used , the compiler will optimize this code */
16263d58139fSopenharmony_ci    return -1;
16273d58139fSopenharmony_ci#endif
16283d58139fSopenharmony_ci    } else {
16293d58139fSopenharmony_ci        *(char *)endPtr = (char)spec->ch;
16303d58139fSopenharmony_ci        endPtr = (char *)endPtr + 1;
16313d58139fSopenharmony_ci        --spec->arrayWidth;
16323d58139fSopenharmony_ci    }
16333d58139fSopenharmony_ci    spec->argPtr = endPtr;
16343d58139fSopenharmony_ci    return 0;
16353d58139fSopenharmony_ci}
16363d58139fSopenharmony_ci#endif
16373d58139fSopenharmony_ci
16383d58139fSopenharmony_ci/*
16393d58139fSopenharmony_ci * Scan digital part of %d %i %o %u %x %p.
16403d58139fSopenharmony_ci * Return 0 OK
16413d58139fSopenharmony_ci */
16423d58139fSopenharmony_ciSECUREC_INLINE int SecInputNumberDigital(SecFileStream *stream, SecScanSpec *spec)
16433d58139fSopenharmony_ci{
16443d58139fSopenharmony_ci    static void (* const secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
16453d58139fSopenharmony_ci        SecFinishNumber, SecFinishNumber64
16463d58139fSopenharmony_ci    };
16473d58139fSopenharmony_ci    while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
16483d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount));
16493d58139fSopenharmony_ci        /* Decode ch to number */
16503d58139fSopenharmony_ci        if (SecDecodeNumber(spec) != 0) {
16513d58139fSopenharmony_ci            SecUnGetChar(spec->ch, stream, &(spec->charCount));
16523d58139fSopenharmony_ci            break;
16533d58139fSopenharmony_ci        }
16543d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
16553d58139fSopenharmony_ci        spec->numberState = SECUREC_NUMBER_STATE_STARTED;
16563d58139fSopenharmony_ci    }
16573d58139fSopenharmony_ci    /* Handling integer negative numbers and beyond max */
16583d58139fSopenharmony_ci    (*secFinishNumber[spec->numberArgType])(spec);
16593d58139fSopenharmony_ci    if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) {
16603d58139fSopenharmony_ci        return 0;
16613d58139fSopenharmony_ci    }
16623d58139fSopenharmony_ci    return -1;
16633d58139fSopenharmony_ci}
16643d58139fSopenharmony_ci
16653d58139fSopenharmony_ci/*
16663d58139fSopenharmony_ci * Scan %d %i %o %u %x %p.
16673d58139fSopenharmony_ci * Return 0 OK
16683d58139fSopenharmony_ci */
16693d58139fSopenharmony_ciSECUREC_INLINE int SecInputNumber(SecFileStream *stream, SecScanSpec *spec)
16703d58139fSopenharmony_ci{
16713d58139fSopenharmony_ci    /* Character already read */
16723d58139fSopenharmony_ci    if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
16733d58139fSopenharmony_ci        if (spec->ch == SECUREC_CHAR('-')) {
16743d58139fSopenharmony_ci            spec->negative = 1;
16753d58139fSopenharmony_ci#if SECUREC_IN_KERNEL
16763d58139fSopenharmony_ci            /* In kernel Refuse to enter negative number */
16773d58139fSopenharmony_ci            if (SECUREC_CONVERT_IS_UNSIGNED(spec->oriConvChr)) {
16783d58139fSopenharmony_ci                return -1;
16793d58139fSopenharmony_ci            }
16803d58139fSopenharmony_ci#endif
16813d58139fSopenharmony_ci        }
16823d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec); /* Do not need to check width here, must be greater than 0 */
16833d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount)); /* Eat + or - */
16843d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next character, used for the '0' judgments */
16853d58139fSopenharmony_ci        SecUnGetChar(spec->ch, stream, &(spec->charCount)); /* Not sure if it was actually read, so push back */
16863d58139fSopenharmony_ci    }
16873d58139fSopenharmony_ci
16883d58139fSopenharmony_ci    if (spec->oriConvChr == 'i') {
16893d58139fSopenharmony_ci        spec->convChr = 'd'; /* The i could be d, o, or x, use d as default */
16903d58139fSopenharmony_ci    }
16913d58139fSopenharmony_ci
16923d58139fSopenharmony_ci    if (spec->ch == SECUREC_CHAR('0') && (spec->oriConvChr == 'x' || spec->oriConvChr == 'i') &&
16933d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_ENOUGH(spec)) {
16943d58139fSopenharmony_ci        /* Input string begin with 0, may be 0x123  0X123  0123  0x  01  0yy  09  0  0ab 00 */
16953d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec);
16963d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount)); /* ch is '0' */
16973d58139fSopenharmony_ci
16983d58139fSopenharmony_ci        /* Read only '0' due to width limitation */
16993d58139fSopenharmony_ci        if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) {
17003d58139fSopenharmony_ci            /* The number or number64 in spec has been set 0 */
17013d58139fSopenharmony_ci            return 0;
17023d58139fSopenharmony_ci        }
17033d58139fSopenharmony_ci
17043d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next char to check x or X, do not dec width */
17053d58139fSopenharmony_ci        if ((SecChar)spec->ch == SECUREC_CHAR('x') || (SecChar)spec->ch == SECUREC_CHAR('X')) {
17063d58139fSopenharmony_ci            spec->convChr = 'x';
17073d58139fSopenharmony_ci            SECUREC_FILED_WIDTH_DEC(spec); /* Make incorrect width for x or X */
17083d58139fSopenharmony_ci        } else {
17093d58139fSopenharmony_ci            if (spec->oriConvChr == 'i') {
17103d58139fSopenharmony_ci                spec->convChr = 'o';
17113d58139fSopenharmony_ci            }
17123d58139fSopenharmony_ci            /* For "0y" "08" "01" "0a" ... ,push the 'y' '8' '1' 'a'  back */
17133d58139fSopenharmony_ci            SecUnGetChar(spec->ch, stream, &(spec->charCount));
17143d58139fSopenharmony_ci            /* Since 0 has been read, it indicates that a valid character has been read */
17153d58139fSopenharmony_ci            spec->numberState = SECUREC_NUMBER_STATE_STARTED;
17163d58139fSopenharmony_ci        }
17173d58139fSopenharmony_ci    }
17183d58139fSopenharmony_ci    return SecInputNumberDigital(stream, spec);
17193d58139fSopenharmony_ci}
17203d58139fSopenharmony_ci
17213d58139fSopenharmony_ci/*
17223d58139fSopenharmony_ci * Scan %c %s %[
17233d58139fSopenharmony_ci * Return 0 OK
17243d58139fSopenharmony_ci */
17253d58139fSopenharmony_ciSECUREC_INLINE int SecInputString(SecFileStream *stream, SecScanSpec *spec,
17263d58139fSopenharmony_ci    const SecBracketTable *bracketTable, int *doneCount)
17273d58139fSopenharmony_ci{
17283d58139fSopenharmony_ci    void *startPtr = spec->argPtr;
17293d58139fSopenharmony_ci    int suppressed = 0;
17303d58139fSopenharmony_ci    int errNoMem = 0;
17313d58139fSopenharmony_ci
17323d58139fSopenharmony_ci    while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
17333d58139fSopenharmony_ci        SECUREC_FILED_WIDTH_DEC(spec);
17343d58139fSopenharmony_ci        spec->ch = SecGetChar(stream, &(spec->charCount));
17353d58139fSopenharmony_ci        /*
17363d58139fSopenharmony_ci         * The char condition or string condition and bracket condition.
17373d58139fSopenharmony_ci         * Only supports wide characters with a maximum length of two bytes
17383d58139fSopenharmony_ci         */
17393d58139fSopenharmony_ci        if (spec->ch != SECUREC_EOF && (SecCanInputCharacter(spec->convChr) != 0 ||
17403d58139fSopenharmony_ci            SecCanInputString(spec->convChr, spec->ch) != 0 ||
17413d58139fSopenharmony_ci            SecCanInputForBracket(spec->convChr, spec->ch, bracketTable) != 0)) {
17423d58139fSopenharmony_ci            if (spec->suppress != 0) {
17433d58139fSopenharmony_ci                /* Used to identify processed data for %*, use argPtr to identify will cause 613, so use suppressed */
17443d58139fSopenharmony_ci                suppressed = 1;
17453d58139fSopenharmony_ci                continue;
17463d58139fSopenharmony_ci            }
17473d58139fSopenharmony_ci            /* Now suppress is not set */
17483d58139fSopenharmony_ci            if (spec->arrayWidth == 0) {
17493d58139fSopenharmony_ci                errNoMem = 1; /* We have exhausted the user's buffer */
17503d58139fSopenharmony_ci                break;
17513d58139fSopenharmony_ci            }
17523d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
17533d58139fSopenharmony_ci            errNoMem = SecInputForWchar(spec);
17543d58139fSopenharmony_ci#else
17553d58139fSopenharmony_ci            errNoMem = SecInputForChar(spec, stream);
17563d58139fSopenharmony_ci#endif
17573d58139fSopenharmony_ci            if (errNoMem != 0) {
17583d58139fSopenharmony_ci                break;
17593d58139fSopenharmony_ci            }
17603d58139fSopenharmony_ci        } else {
17613d58139fSopenharmony_ci            SecUnGetChar(spec->ch, stream, &(spec->charCount));
17623d58139fSopenharmony_ci            break;
17633d58139fSopenharmony_ci        }
17643d58139fSopenharmony_ci    }
17653d58139fSopenharmony_ci
17663d58139fSopenharmony_ci    if (errNoMem != 0) {
17673d58139fSopenharmony_ci        /* In case of error, blank out the input buffer */
17683d58139fSopenharmony_ci        SecAddEndingZero(startPtr, spec);
17693d58139fSopenharmony_ci        return -1;
17703d58139fSopenharmony_ci    }
17713d58139fSopenharmony_ci    if ((spec->suppress != 0 && suppressed == 0) ||
17723d58139fSopenharmony_ci        (spec->suppress == 0 && startPtr == spec->argPtr)) {
17733d58139fSopenharmony_ci        /* No input was scanned */
17743d58139fSopenharmony_ci        return -1;
17753d58139fSopenharmony_ci    }
17763d58139fSopenharmony_ci    if (spec->convChr != 'c') {
17773d58139fSopenharmony_ci        /* Add null-terminate for strings */
17783d58139fSopenharmony_ci        SecAddEndingZero(spec->argPtr, spec);
17793d58139fSopenharmony_ci    }
17803d58139fSopenharmony_ci    if (spec->suppress == 0) {
17813d58139fSopenharmony_ci        *doneCount = *doneCount + 1;
17823d58139fSopenharmony_ci    }
17833d58139fSopenharmony_ci    return 0;
17843d58139fSopenharmony_ci}
17853d58139fSopenharmony_ci
17863d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
17873d58139fSopenharmony_ci/*
17883d58139fSopenharmony_ci * Allocate buffer for wchar version of %[.
17893d58139fSopenharmony_ci * Return 0 OK
17903d58139fSopenharmony_ci */
17913d58139fSopenharmony_ciSECUREC_INLINE int SecAllocBracketTable(SecBracketTable *bracketTable)
17923d58139fSopenharmony_ci{
17933d58139fSopenharmony_ci    if (bracketTable->table == NULL) {
17943d58139fSopenharmony_ci        /* Table should be freed after use */
17953d58139fSopenharmony_ci        bracketTable->table = (unsigned char *)SECUREC_MALLOC(SECUREC_BRACKET_TABLE_SIZE);
17963d58139fSopenharmony_ci        if (bracketTable->table == NULL) {
17973d58139fSopenharmony_ci            return -1;
17983d58139fSopenharmony_ci        }
17993d58139fSopenharmony_ci    }
18003d58139fSopenharmony_ci    return 0;
18013d58139fSopenharmony_ci}
18023d58139fSopenharmony_ci
18033d58139fSopenharmony_ci/*
18043d58139fSopenharmony_ci * Free buffer for wchar version of %[
18053d58139fSopenharmony_ci */
18063d58139fSopenharmony_ciSECUREC_INLINE void SecFreeBracketTable(SecBracketTable *bracketTable)
18073d58139fSopenharmony_ci{
18083d58139fSopenharmony_ci    if (bracketTable->table != NULL) {
18093d58139fSopenharmony_ci        SECUREC_FREE(bracketTable->table);
18103d58139fSopenharmony_ci        bracketTable->table = NULL;
18113d58139fSopenharmony_ci    }
18123d58139fSopenharmony_ci}
18133d58139fSopenharmony_ci#endif
18143d58139fSopenharmony_ci
18153d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
18163d58139fSopenharmony_ci/*
18173d58139fSopenharmony_ci *  Formatting input core functions for wchar version.Called by a function such as vswscanf_s
18183d58139fSopenharmony_ci */
18193d58139fSopenharmony_ciint SecInputSW(SecFileStream *stream, const wchar_t *cFormat, va_list argList)
18203d58139fSopenharmony_ci#else
18213d58139fSopenharmony_ci/*
18223d58139fSopenharmony_ci * Formatting input core functions for char version.Called by a function such as vsscanf_s
18233d58139fSopenharmony_ci */
18243d58139fSopenharmony_ciint SecInputS(SecFileStream *stream, const char *cFormat, va_list argList)
18253d58139fSopenharmony_ci#endif
18263d58139fSopenharmony_ci{
18273d58139fSopenharmony_ci    const SecUnsignedChar *format = (const SecUnsignedChar *)cFormat;
18283d58139fSopenharmony_ci    SecBracketTable bracketTable = SECUREC_INIT_BRACKET_TABLE;
18293d58139fSopenharmony_ci    SecScanSpec spec;
18303d58139fSopenharmony_ci    int doneCount = 0;
18313d58139fSopenharmony_ci    int formatError = 0;
18323d58139fSopenharmony_ci    int paraIsNull = 0;
18333d58139fSopenharmony_ci    int match = 0; /* When % is found , inc this value */
18343d58139fSopenharmony_ci    int errRet = 0;
18353d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT
18363d58139fSopenharmony_ci    SecFloatSpec floatSpec;
18373d58139fSopenharmony_ci    SecInitFloatSpec(&floatSpec);
18383d58139fSopenharmony_ci#endif
18393d58139fSopenharmony_ci    spec.ch = 0; /* Need to initialize to 0 */
18403d58139fSopenharmony_ci    spec.charCount = 0; /* Need to initialize to 0 */
18413d58139fSopenharmony_ci
18423d58139fSopenharmony_ci    /* Format must not NULL, use err < 1 to clear 845 */
18433d58139fSopenharmony_ci    while (errRet < 1 && *format != SECUREC_CHAR('\0')) {
18443d58139fSopenharmony_ci        /* Skip space in format and space in input */
18453d58139fSopenharmony_ci        if (SecIsSpace((SecInt)(int)(*format)) != 0) {
18463d58139fSopenharmony_ci            /* Read first no space char */
18473d58139fSopenharmony_ci            spec.ch = SecSkipSpaceChar(stream, &(spec.charCount));
18483d58139fSopenharmony_ci            /* Read the EOF cannot be returned directly here, because the case of " %n" needs to be handled */
18493d58139fSopenharmony_ci            /* Put fist no space char backup. put EOF back is also OK, and to modify the character count */
18503d58139fSopenharmony_ci            SecUnGetChar(spec.ch, stream, &(spec.charCount));
18513d58139fSopenharmony_ci            SecSkipSpaceFormat(&format);
18523d58139fSopenharmony_ci            continue;
18533d58139fSopenharmony_ci        }
18543d58139fSopenharmony_ci
18553d58139fSopenharmony_ci        if (*format != SECUREC_CHAR('%')) {
18563d58139fSopenharmony_ci            spec.ch = SecGetChar(stream, &(spec.charCount));
18573d58139fSopenharmony_ci            if ((int)(*format) != (int)(spec.ch)) {
18583d58139fSopenharmony_ci                SecUnGetChar(spec.ch, stream, &(spec.charCount));
18593d58139fSopenharmony_ci                break;
18603d58139fSopenharmony_ci            }
18613d58139fSopenharmony_ci            ++format;
18623d58139fSopenharmony_ci#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)
18633d58139fSopenharmony_ci            if (SecFilterWcharInFormat(&spec, &format, stream) != 0) {
18643d58139fSopenharmony_ci                break;
18653d58139fSopenharmony_ci            }
18663d58139fSopenharmony_ci#endif
18673d58139fSopenharmony_ci            continue;
18683d58139fSopenharmony_ci        }
18693d58139fSopenharmony_ci
18703d58139fSopenharmony_ci        /* Now *format is % */
18713d58139fSopenharmony_ci        /* Set default value for each % */
18723d58139fSopenharmony_ci        SecSetDefaultScanSpec(&spec);
18733d58139fSopenharmony_ci        if (SecDecodeScanFlag(&format, &spec) != 0) {
18743d58139fSopenharmony_ci            formatError = 1;
18753d58139fSopenharmony_ci            ++errRet;
18763d58139fSopenharmony_ci            continue;
18773d58139fSopenharmony_ci        }
18783d58139fSopenharmony_ci        if (!SECUREC_FILED_WIDTH_ENOUGH(&spec)) {
18793d58139fSopenharmony_ci            /* 0 width in format */
18803d58139fSopenharmony_ci            ++errRet;
18813d58139fSopenharmony_ci            continue;
18823d58139fSopenharmony_ci        }
18833d58139fSopenharmony_ci
18843d58139fSopenharmony_ci        /* Update wchar flag for %S %C */
18853d58139fSopenharmony_ci        SecUpdateWcharFlagByType(*format, &spec);
18863d58139fSopenharmony_ci
18873d58139fSopenharmony_ci        spec.convChr = SECUREC_TO_LOWERCASE(*format);
18883d58139fSopenharmony_ci        spec.oriConvChr = spec.convChr; /* convChr may be modified to handle integer logic */
18893d58139fSopenharmony_ci        if (spec.convChr != 'n') {
18903d58139fSopenharmony_ci            if (spec.convChr != 'c' && spec.convChr != SECUREC_BRACE) {
18913d58139fSopenharmony_ci                spec.ch = SecSkipSpaceChar(stream, &(spec.charCount));
18923d58139fSopenharmony_ci            } else {
18933d58139fSopenharmony_ci                spec.ch = SecGetChar(stream, &(spec.charCount));
18943d58139fSopenharmony_ci            }
18953d58139fSopenharmony_ci            if (spec.ch == SECUREC_EOF) {
18963d58139fSopenharmony_ci                ++errRet;
18973d58139fSopenharmony_ci                continue;
18983d58139fSopenharmony_ci            }
18993d58139fSopenharmony_ci        }
19003d58139fSopenharmony_ci
19013d58139fSopenharmony_ci        /* Now no 0 width in format and get one char from input */
19023d58139fSopenharmony_ci        switch (spec.oriConvChr) {
19033d58139fSopenharmony_ci            case 'c': /* Also 'C' */
19043d58139fSopenharmony_ci                if (spec.widthSet == 0) {
19053d58139fSopenharmony_ci                    spec.widthSet = 1;
19063d58139fSopenharmony_ci                    spec.width = 1;
19073d58139fSopenharmony_ci                }
19083d58139fSopenharmony_ci                /* fall-through */ /* FALLTHRU */
19093d58139fSopenharmony_ci            case 's': /* Also 'S': */
19103d58139fSopenharmony_ci                /* fall-through */ /* FALLTHRU */
19113d58139fSopenharmony_ci            case SECUREC_BRACE:
19123d58139fSopenharmony_ci                /* Unset last char to stream */
19133d58139fSopenharmony_ci                SecUnGetChar(spec.ch, stream, &(spec.charCount));
19143d58139fSopenharmony_ci                /* Check dest buffer and size */
19153d58139fSopenharmony_ci                if (spec.suppress == 0) {
19163d58139fSopenharmony_ci                    spec.argPtr = (void *)va_arg(argList, void *);
19173d58139fSopenharmony_ci                    if (spec.argPtr == NULL) {
19183d58139fSopenharmony_ci                        paraIsNull = 1;
19193d58139fSopenharmony_ci                        ++errRet;
19203d58139fSopenharmony_ci                        continue;
19213d58139fSopenharmony_ci                    }
19223d58139fSopenharmony_ci                    /* Get the next argument, size of the array in characters */
19233d58139fSopenharmony_ci                    spec.arrayWidth = SECUREC_GET_ARRAYWIDTH(argList);
19243d58139fSopenharmony_ci                    if (SECUREC_ARRAY_WIDTH_IS_WRONG(spec)) {
19253d58139fSopenharmony_ci                        /* Do not clear buffer just go error */
19263d58139fSopenharmony_ci                        ++errRet;
19273d58139fSopenharmony_ci                        continue;
19283d58139fSopenharmony_ci                    }
19293d58139fSopenharmony_ci                    /* One element is needed for '\0' for %s and %[ */
19303d58139fSopenharmony_ci                    if (spec.convChr != 'c') {
19313d58139fSopenharmony_ci                        --spec.arrayWidth;
19323d58139fSopenharmony_ci                    }
19333d58139fSopenharmony_ci                } else {
19343d58139fSopenharmony_ci                    /* Set argPtr to  NULL  is necessary, in suppress mode we don't use argPtr to store data */
19353d58139fSopenharmony_ci                    spec.argPtr = NULL;
19363d58139fSopenharmony_ci                }
19373d58139fSopenharmony_ci
19383d58139fSopenharmony_ci                if (spec.convChr == SECUREC_BRACE) {
19393d58139fSopenharmony_ci                    /* Malloc when first %[ is meet  for wchar version */
19403d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
19413d58139fSopenharmony_ci                    if (SecAllocBracketTable(&bracketTable) != 0) {
19423d58139fSopenharmony_ci                        ++errRet;
19433d58139fSopenharmony_ci                        continue;
19443d58139fSopenharmony_ci                    }
19453d58139fSopenharmony_ci#endif
19463d58139fSopenharmony_ci                    (void)SECUREC_MEMSET_FUNC_OPT(bracketTable.table, 0, (size_t)SECUREC_BRACKET_TABLE_SIZE);
19473d58139fSopenharmony_ci                    if (SecSetupBracketTable(&format, &bracketTable) != 0) {
19483d58139fSopenharmony_ci                        ++errRet;
19493d58139fSopenharmony_ci                        continue;
19503d58139fSopenharmony_ci                    }
19513d58139fSopenharmony_ci
19523d58139fSopenharmony_ci                    if (*format == SECUREC_CHAR('\0')) {
19533d58139fSopenharmony_ci                        /* Default add string terminator */
19543d58139fSopenharmony_ci                        SecAddEndingZero(spec.argPtr, &spec);
19553d58139fSopenharmony_ci                        ++errRet;
19563d58139fSopenharmony_ci                        /* Truncated format */
19573d58139fSopenharmony_ci                        continue;
19583d58139fSopenharmony_ci                    }
19593d58139fSopenharmony_ci                }
19603d58139fSopenharmony_ci
19613d58139fSopenharmony_ci                /* Set completed.  Now read string or character */
19623d58139fSopenharmony_ci                if (SecInputString(stream, &spec, &bracketTable, &doneCount) != 0) {
19633d58139fSopenharmony_ci                    ++errRet;
19643d58139fSopenharmony_ci                    continue;
19653d58139fSopenharmony_ci                }
19663d58139fSopenharmony_ci                break;
19673d58139fSopenharmony_ci            case 'p':
19683d58139fSopenharmony_ci                /* Make %hp same as %p */
19693d58139fSopenharmony_ci                spec.numberWidth = SECUREC_NUM_WIDTH_INT;
19703d58139fSopenharmony_ci#ifdef SECUREC_ON_64BITS
19713d58139fSopenharmony_ci                spec.numberArgType = 1;
19723d58139fSopenharmony_ci#endif
19733d58139fSopenharmony_ci                /* fall-through */ /* FALLTHRU */
19743d58139fSopenharmony_ci            case 'o': /* fall-through */ /* FALLTHRU */
19753d58139fSopenharmony_ci            case 'u': /* fall-through */ /* FALLTHRU */
19763d58139fSopenharmony_ci            case 'd': /* fall-through */ /* FALLTHRU */
19773d58139fSopenharmony_ci            case 'i': /* fall-through */ /* FALLTHRU */
19783d58139fSopenharmony_ci            case 'x':
19793d58139fSopenharmony_ci                /* Unset last char to stream */
19803d58139fSopenharmony_ci                SecUnGetChar(spec.ch, stream, &(spec.charCount));
19813d58139fSopenharmony_ci                if (SecInputNumber(stream, &spec) != 0) {
19823d58139fSopenharmony_ci                    ++errRet;
19833d58139fSopenharmony_ci                    continue;
19843d58139fSopenharmony_ci                }
19853d58139fSopenharmony_ci                if (spec.suppress == 0) {
19863d58139fSopenharmony_ci                    spec.argPtr = (void *)va_arg(argList, void *);
19873d58139fSopenharmony_ci                    if (spec.argPtr == NULL) {
19883d58139fSopenharmony_ci                        paraIsNull = 1;
19893d58139fSopenharmony_ci                        ++errRet;
19903d58139fSopenharmony_ci                        continue;
19913d58139fSopenharmony_ci                    }
19923d58139fSopenharmony_ci                    SecAssignNumber(&spec);
19933d58139fSopenharmony_ci                    ++doneCount;
19943d58139fSopenharmony_ci                }
19953d58139fSopenharmony_ci                break;
19963d58139fSopenharmony_ci            case 'n': /* Char count */
19973d58139fSopenharmony_ci                if (spec.suppress == 0) {
19983d58139fSopenharmony_ci                    spec.argPtr = (void *)va_arg(argList, void *);
19993d58139fSopenharmony_ci                    if (spec.argPtr == NULL) {
20003d58139fSopenharmony_ci                        paraIsNull = 1;
20013d58139fSopenharmony_ci                        ++errRet;
20023d58139fSopenharmony_ci                        continue;
20033d58139fSopenharmony_ci                    }
20043d58139fSopenharmony_ci                    spec.number = (unsigned long)(unsigned int)(spec.charCount);
20053d58139fSopenharmony_ci                    spec.numberArgType = 0;
20063d58139fSopenharmony_ci                    SecAssignNumber(&spec);
20073d58139fSopenharmony_ci                }
20083d58139fSopenharmony_ci                break;
20093d58139fSopenharmony_ci            case 'e': /* fall-through */ /* FALLTHRU */
20103d58139fSopenharmony_ci            case 'f': /* fall-through */ /* FALLTHRU */
20113d58139fSopenharmony_ci            case 'g': /* Scan a float */
20123d58139fSopenharmony_ci                /* Unset last char to stream */
20133d58139fSopenharmony_ci                SecUnGetChar(spec.ch, stream, &(spec.charCount));
20143d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT
20153d58139fSopenharmony_ci                if (SecInputFloat(stream, &spec, &floatSpec) != 0) {
20163d58139fSopenharmony_ci                    ++errRet;
20173d58139fSopenharmony_ci                    continue;
20183d58139fSopenharmony_ci                }
20193d58139fSopenharmony_ci                if (spec.suppress == 0) {
20203d58139fSopenharmony_ci                    spec.argPtr = (void *)va_arg(argList, void *);
20213d58139fSopenharmony_ci                    if (spec.argPtr == NULL) {
20223d58139fSopenharmony_ci                        ++errRet;
20233d58139fSopenharmony_ci                        paraIsNull = 1;
20243d58139fSopenharmony_ci                        continue;
20253d58139fSopenharmony_ci                    }
20263d58139fSopenharmony_ci                    if (SecAssignFloat(&floatSpec, &spec) != 0) {
20273d58139fSopenharmony_ci                        ++errRet;
20283d58139fSopenharmony_ci                        continue;
20293d58139fSopenharmony_ci                    }
20303d58139fSopenharmony_ci                    ++doneCount;
20313d58139fSopenharmony_ci                }
20323d58139fSopenharmony_ci                break;
20333d58139fSopenharmony_ci#else /* SECUREC_ENABLE_SCANF_FLOAT */
20343d58139fSopenharmony_ci                ++errRet;
20353d58139fSopenharmony_ci                continue;
20363d58139fSopenharmony_ci#endif
20373d58139fSopenharmony_ci            default:
20383d58139fSopenharmony_ci                if ((int)(*format) != (int)spec.ch) {
20393d58139fSopenharmony_ci                    SecUnGetChar(spec.ch, stream, &(spec.charCount));
20403d58139fSopenharmony_ci                    formatError = 1;
20413d58139fSopenharmony_ci                    ++errRet;
20423d58139fSopenharmony_ci                    continue;
20433d58139fSopenharmony_ci                } else {
20443d58139fSopenharmony_ci                    --match; /* Compensate for the self-increment of the following code */
20453d58139fSopenharmony_ci                }
20463d58139fSopenharmony_ci                break;
20473d58139fSopenharmony_ci        }
20483d58139fSopenharmony_ci        ++match;
20493d58139fSopenharmony_ci        ++format;
20503d58139fSopenharmony_ci    }
20513d58139fSopenharmony_ci
20523d58139fSopenharmony_ci#ifdef SECUREC_FOR_WCHAR
20533d58139fSopenharmony_ci    SecFreeBracketTable(&bracketTable);
20543d58139fSopenharmony_ci#endif
20553d58139fSopenharmony_ci
20563d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FLOAT
20573d58139fSopenharmony_ci    SecFreeFloatSpec(&floatSpec, &doneCount);
20583d58139fSopenharmony_ci#endif
20593d58139fSopenharmony_ci
20603d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE
20613d58139fSopenharmony_ci    SecAdjustStream(stream);
20623d58139fSopenharmony_ci#endif
20633d58139fSopenharmony_ci
20643d58139fSopenharmony_ci    if (spec.ch == SECUREC_EOF) {
20653d58139fSopenharmony_ci        return ((doneCount != 0 || match != 0) ? doneCount : SECUREC_SCANF_EINVAL);
20663d58139fSopenharmony_ci    }
20673d58139fSopenharmony_ci    if (formatError != 0 || paraIsNull != 0) {
20683d58139fSopenharmony_ci        /* Invalid Input Format or parameter, but not meet EOF */
20693d58139fSopenharmony_ci        return SECUREC_SCANF_ERROR_PARA;
20703d58139fSopenharmony_ci    }
20713d58139fSopenharmony_ci    return doneCount;
20723d58139fSopenharmony_ci}
20733d58139fSopenharmony_ci
20743d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE
20753d58139fSopenharmony_ci/*
20763d58139fSopenharmony_ci *  Get char from stream use std function
20773d58139fSopenharmony_ci */
20783d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetCharFromStream(const SecFileStream *stream)
20793d58139fSopenharmony_ci{
20803d58139fSopenharmony_ci    SecInt ch;
20813d58139fSopenharmony_ci    ch = SECUREC_GETC(stream->pf);
20823d58139fSopenharmony_ci    return ch;
20833d58139fSopenharmony_ci}
20843d58139fSopenharmony_ci
20853d58139fSopenharmony_ci/*
20863d58139fSopenharmony_ci * Try to read the BOM header, when meet a BOM head, discard it, then data is Aligned to base
20873d58139fSopenharmony_ci */
20883d58139fSopenharmony_ciSECUREC_INLINE void SecReadAndSkipBomHeader(SecFileStream *stream)
20893d58139fSopenharmony_ci{
20903d58139fSopenharmony_ci    /* Use size_t type conversion  to clean e747 */
20913d58139fSopenharmony_ci    stream->count = fread(stream->base, (size_t)1, (size_t)SECUREC_BOM_HEADER_SIZE, stream->pf);
20923d58139fSopenharmony_ci    if (stream->count > SECUREC_BOM_HEADER_SIZE) {
20933d58139fSopenharmony_ci        stream->count = 0;
20943d58139fSopenharmony_ci    }
20953d58139fSopenharmony_ci    if (SECUREC_BEGIN_WITH_BOM(stream->base, stream->count)) {
20963d58139fSopenharmony_ci        /* It's BOM header, discard it */
20973d58139fSopenharmony_ci        stream->count = 0;
20983d58139fSopenharmony_ci    }
20993d58139fSopenharmony_ci}
21003d58139fSopenharmony_ci
21013d58139fSopenharmony_ci/*
21023d58139fSopenharmony_ci *  Get char  from file stream or buffer
21033d58139fSopenharmony_ci */
21043d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetCharFromFile(SecFileStream *stream)
21053d58139fSopenharmony_ci{
21063d58139fSopenharmony_ci    SecInt ch;
21073d58139fSopenharmony_ci    if (stream->count < sizeof(SecChar)) {
21083d58139fSopenharmony_ci        /* Load file to buffer */
21093d58139fSopenharmony_ci        size_t len;
21103d58139fSopenharmony_ci        if (stream->base != NULL) {
21113d58139fSopenharmony_ci            /* Put the last unread data in the buffer head */
21123d58139fSopenharmony_ci            for (len = 0; len < stream->count; ++len) {
21133d58139fSopenharmony_ci                stream->base[len] = stream->cur[len];
21143d58139fSopenharmony_ci            }
21153d58139fSopenharmony_ci        } else {
21163d58139fSopenharmony_ci            stream->oriFilePos = ftell(stream->pf);   /* Save original file read position */
21173d58139fSopenharmony_ci            if (stream->oriFilePos == -1) {
21183d58139fSopenharmony_ci                /* It may be a pipe stream */
21193d58139fSopenharmony_ci                stream->flag = SECUREC_PIPE_STREAM_FLAG;
21203d58139fSopenharmony_ci                return SecGetCharFromStream(stream);
21213d58139fSopenharmony_ci            }
21223d58139fSopenharmony_ci            /* Reserve the length of BOM head */
21233d58139fSopenharmony_ci            stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE +
21243d58139fSopenharmony_ci                SECUREC_BOM_HEADER_SIZE + sizeof(SecChar)); /* To store '\0' and aligned to wide char */
21253d58139fSopenharmony_ci            if (stream->base == NULL) {
21263d58139fSopenharmony_ci                return SECUREC_EOF;
21273d58139fSopenharmony_ci            }
21283d58139fSopenharmony_ci            /* First read file */
21293d58139fSopenharmony_ci            if (stream->oriFilePos == 0) {
21303d58139fSopenharmony_ci                /* Make sure the data is aligned to base */
21313d58139fSopenharmony_ci                SecReadAndSkipBomHeader(stream);
21323d58139fSopenharmony_ci            }
21333d58139fSopenharmony_ci        }
21343d58139fSopenharmony_ci
21353d58139fSopenharmony_ci        /* Skip existing data and read data */
21363d58139fSopenharmony_ci        len = fread(stream->base + stream->count, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf);
21373d58139fSopenharmony_ci        if (len > SECUREC_BUFFERED_BLOK_SIZE) { /* It won't happen, */
21383d58139fSopenharmony_ci            len = 0;
21393d58139fSopenharmony_ci        }
21403d58139fSopenharmony_ci        stream->count += len;
21413d58139fSopenharmony_ci        stream->cur = stream->base;
21423d58139fSopenharmony_ci        stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG;
21433d58139fSopenharmony_ci        stream->base[stream->count] = '\0';   /* For tool Warning string null */
21443d58139fSopenharmony_ci    }
21453d58139fSopenharmony_ci
21463d58139fSopenharmony_ci    SECUREC_GET_CHAR(stream, &ch);
21473d58139fSopenharmony_ci    if (ch != SECUREC_EOF) {
21483d58139fSopenharmony_ci        stream->fileRealRead += sizeof(SecChar);
21493d58139fSopenharmony_ci    }
21503d58139fSopenharmony_ci    return ch;
21513d58139fSopenharmony_ci}
21523d58139fSopenharmony_ci#endif
21533d58139fSopenharmony_ci
21543d58139fSopenharmony_ci/*
21553d58139fSopenharmony_ci *  Get char  for wchar version
21563d58139fSopenharmony_ci */
21573d58139fSopenharmony_ciSECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter)
21583d58139fSopenharmony_ci{
21593d58139fSopenharmony_ci    *counter = *counter + 1; /* Always plus 1 */
21603d58139fSopenharmony_ci    /* The main scenario is scanf str */
21613d58139fSopenharmony_ci    if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) {
21623d58139fSopenharmony_ci        SecInt ch;
21633d58139fSopenharmony_ci        SECUREC_GET_CHAR(stream, &ch);
21643d58139fSopenharmony_ci        return ch;
21653d58139fSopenharmony_ci    }
21663d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE
21673d58139fSopenharmony_ci    if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0) {
21683d58139fSopenharmony_ci        return SecGetCharFromFile(stream);
21693d58139fSopenharmony_ci    }
21703d58139fSopenharmony_ci    if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) {
21713d58139fSopenharmony_ci        return SecGetCharFromStream(stream);
21723d58139fSopenharmony_ci    }
21733d58139fSopenharmony_ci#endif
21743d58139fSopenharmony_ci    return SECUREC_EOF;
21753d58139fSopenharmony_ci}
21763d58139fSopenharmony_ci
21773d58139fSopenharmony_ci/*
21783d58139fSopenharmony_ci *  Unget Public realization char for wchar and char version
21793d58139fSopenharmony_ci */
21803d58139fSopenharmony_ciSECUREC_INLINE void SecUnGetCharImpl(SecInt ch, SecFileStream *stream)
21813d58139fSopenharmony_ci{
21823d58139fSopenharmony_ci    if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) {
21833d58139fSopenharmony_ci        SECUREC_UN_GET_CHAR(stream);
21843d58139fSopenharmony_ci        return;
21853d58139fSopenharmony_ci    }
21863d58139fSopenharmony_ci#if SECUREC_ENABLE_SCANF_FILE
21873d58139fSopenharmony_ci    if ((stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) != 0) {
21883d58139fSopenharmony_ci        SECUREC_UN_GET_CHAR(stream);
21893d58139fSopenharmony_ci        if (stream->fileRealRead > 0) {
21903d58139fSopenharmony_ci            stream->fileRealRead -= sizeof(SecChar);
21913d58139fSopenharmony_ci        }
21923d58139fSopenharmony_ci        return;
21933d58139fSopenharmony_ci    }
21943d58139fSopenharmony_ci    if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) {
21953d58139fSopenharmony_ci        (void)SECUREC_UN_GETC(ch, stream->pf);
21963d58139fSopenharmony_ci        return;
21973d58139fSopenharmony_ci    }
21983d58139fSopenharmony_ci#else
21993d58139fSopenharmony_ci    (void)ch; /* To clear e438 last value assigned not used , the compiler will optimize this code */
22003d58139fSopenharmony_ci#endif
22013d58139fSopenharmony_ci}
22023d58139fSopenharmony_ci
22033d58139fSopenharmony_ci/*
22043d58139fSopenharmony_ci *  Unget char  for char version
22053d58139fSopenharmony_ci */
22063d58139fSopenharmony_ciSECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter)
22073d58139fSopenharmony_ci{
22083d58139fSopenharmony_ci    *counter = *counter - 1; /* Always minus 1 */
22093d58139fSopenharmony_ci    if (ch != SECUREC_EOF) {
22103d58139fSopenharmony_ci        SecUnGetCharImpl(ch, stream);
22113d58139fSopenharmony_ci    }
22123d58139fSopenharmony_ci}
22133d58139fSopenharmony_ci
22143d58139fSopenharmony_ci/*
22153d58139fSopenharmony_ci *  Skip space char by isspace
22163d58139fSopenharmony_ci */
22173d58139fSopenharmony_ciSECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter)
22183d58139fSopenharmony_ci{
22193d58139fSopenharmony_ci    SecInt ch;
22203d58139fSopenharmony_ci    do {
22213d58139fSopenharmony_ci        ch = SecGetChar(stream, counter);
22223d58139fSopenharmony_ci        if (ch == SECUREC_EOF) {
22233d58139fSopenharmony_ci            break;
22243d58139fSopenharmony_ci        }
22253d58139fSopenharmony_ci    } while (SecIsSpace(ch) != 0);
22263d58139fSopenharmony_ci    return ch;
22273d58139fSopenharmony_ci}
22283d58139fSopenharmony_ci#endif /* INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 */
22293d58139fSopenharmony_ci
2230