text: /*
   * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved.
   *
   * OpenArkCompiler is licensed under the Mulan PSL v1.
   * You can use this software according to the terms and conditions of the Mulan PSL v1.
   * You may obtain a copy of Mulan PSL v1 at:
   *
   *     http://license.coscl.org.cn/MulanPSL
   *
   * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR
   * FIT FOR A PARTICULAR PURPOSE.
   * See the Mulan PSL v1 for more details.
   */
  /*
   * [Standardize-exceptions] Use unsafe function: Performance-sensitive
   * [reason] Always used in the performance critical path,
   *          and sufficient input validation is performed before calling
   */
  
  #ifndef INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
  #define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
  
  #if SECUREC_IN_KERNEL
  #if !defined(SECUREC_CTYPE_MACRO_ADAPT)
  #include <linux/ctype.h>
  #endif
  #ifndef EOF
  #define EOF  (-1)
  #endif
  #else
  #if !defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT)
  #include <ctype.h>
  #ifdef SECUREC_FOR_WCHAR
  #include <wctype.h>             /* For iswspace */
  #endif
  #endif
  #endif
  
  #define SECUREC_NUM_WIDTH_SHORT                 0
  #define SECUREC_NUM_WIDTH_INT                   1
  #define SECUREC_NUM_WIDTH_LONG                  2
  #define SECUREC_NUM_WIDTH_LONG_LONG             3 /* Also long double */
  
  #define SECUREC_BUFFERED_BLOK_SIZE              1024
  
  #if defined(SECUREC_VXWORKS_PLATFORM) && !defined(va_copy) && !defined(__va_copy)
  /* The name is the same as system macro. */
  #define __va_copy(d, s) do { \
      size_t size_of_d = (size_t)sizeof(d); \
      size_t size_of_s = (size_t)sizeof(s); \
      if (size_of_d != size_of_s) { \
          (void)memcpy((d), (s), sizeof(va_list)); \
      } else { \
          (void)memcpy(&(d), &(s), sizeof(va_list)); \
      } \
  } SECUREC_WHILE_ZERO
  #endif
  
  
  #define SECUREC_MULTI_BYTE_MAX_LEN              6
  
  /* Compatibility macro name cannot be modifie */
  #ifndef UNALIGNED
  #if !(defined(_M_IA64)) && !(defined(_M_AMD64))
  #define UNALIGNED
  #else
  #define UNALIGNED __unaligned
  #endif
  #endif
  
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
  /* Max 64bit value is 0xffffffffffffffff */
  #define SECUREC_MAX_64BITS_VALUE                18446744073709551615ULL
  #define SECUREC_MAX_64BITS_VALUE_DIV_TEN        1844674407370955161ULL
  #define SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT 18446744073709551610ULL
  #define SECUREC_MIN_64BITS_NEG_VALUE            9223372036854775808ULL
  #define SECUREC_MAX_64BITS_POS_VALUE            9223372036854775807ULL
  #define SECUREC_MIN_32BITS_NEG_VALUE            2147483648ULL
  #define SECUREC_MAX_32BITS_POS_VALUE            2147483647ULL
  #define SECUREC_MAX_32BITS_VALUE                4294967295ULL
  #define SECUREC_MAX_32BITS_VALUE_INC            4294967296ULL
  #define SECUREC_MAX_32BITS_VALUE_DIV_TEN        429496729ULL
  #define SECUREC_LONG_BIT_NUM                    ((unsigned int)(sizeof(long) << 3U))
  /* Use ULL to clean up cl6x compilation alerts */
  #define SECUREC_MAX_LONG_POS_VALUE              ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)) - 1)
  #define SECUREC_MIN_LONG_NEG_VALUE              ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)))
  
  /* Covert to long long to clean up cl6x compilation alerts */
  #define SECUREC_LONG_HEX_BEYOND_MAX(number)     (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0)
  #define SECUREC_LONG_OCTAL_BEYOND_MAX(number)   (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 3U)) > 0)
  
  #define SECUREC_QWORD_HEX_BEYOND_MAX(number)    (((number) >> (64U - 4U)) > 0)
  #define SECUREC_QWORD_OCTAL_BEYOND_MAX(number)  (((number) >> (64U - 3U)) > 0)
  
  #define SECUREC_LP64_BIT_WIDTH                  64
  #define SECUREC_LP32_BIT_WIDTH                  32
  #endif
  
  #define SECUREC_CHAR(x)                         (x)
  #define SECUREC_BRACE                           '{'     /* [ to { */
  
  #ifdef SECUREC_FOR_WCHAR
  /* Bits for all wchar, size is 65536/8, only supports wide characters with a maximum length of two bytes */
  #define SECUREC_BRACKET_TABLE_SIZE    8192
  #define SECUREC_EOF WEOF
  #define SECUREC_MB_LEN 16       /* Max. # bytes in multibyte char  ,see MB_LEN_MAX */
  #else
  /* Bits for all char, size is 256/8 */
  #define SECUREC_BRACKET_TABLE_SIZE    32
  #define SECUREC_EOF EOF
  #endif
  
  #if SECUREC_HAVE_WCHART
  #define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \
      ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN) || \
      ((spec).isWCharOrLong > 0 && (spec).arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN))
  #else
  #define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \
      ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN))
  #endif
  
  /* For next %n */
  #define SECUREC_MEET_EOF_BEFORE_NEXT_N(ch, format) (((ch) == SECUREC_EOF) && \
      ((*(format) != SECUREC_CHAR('%')) || (*((format) + 1) != SECUREC_CHAR('n'))))
  
  typedef struct {
  #ifdef SECUREC_FOR_WCHAR
      unsigned char *table; /* Default NULL */
  #else
      unsigned char table[SECUREC_BRACKET_TABLE_SIZE]; /* Array length is large enough in application scenarios */
  #endif
      unsigned char mask; /* Default 0 */
  } SecBracketTable;
  
  #ifdef SECUREC_FOR_WCHAR
  #define SECUREC_INIT_BRACKET_TABLE { NULL, 0 }
  #else
  #define SECUREC_INIT_BRACKET_TABLE { {0}, 0 }
  #endif
  
  #if SECUREC_ENABLE_SCANF_FLOAT
  typedef struct {
      size_t floatStrTotalLen;       /* Initialization must be length of buffer in charater */
      size_t floatStrUsedLen;        /* Store float string len */
      SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1];
      SecChar *floatStr;             /* Initialization must point to buffer */
      SecChar *allocatedFloatStr;    /* Initialization must be NULL  to store alloced point */
  } SecFloatSpec;
  #endif
  
  typedef struct {
      SecInt ch;            /* Char read from input */
      int charCount;        /* Number of characters processed */
      SecUnsignedInt64 number64;
      unsigned long number;
      int numberWidth;      /* 0 = SHORT, 1 = int, > 1  long or L_DOUBLE */
      int isInt64Arg;       /* 1 for 64-bit integer, 0 otherwise */
      int negative;         /* 0 is positive */
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      int beyondMax;        /* Non-zero means beyond */
  #endif
      void *argPtr;         /* Variable parameter pointer */
      size_t arrayWidth;    /* Length of pointer Variable parameter, in charaters */
      int width;            /* Width number in format */
      int widthSet;         /* 0 is not set width in format */
      int convChr;          /* Lowercase format conversion characters */
      int oriConvChr;       /* Store  original format conversion, convChr may change when parsing integers */
      signed char isWCharOrLong;  /* -1/0 not wchar or long, 1 for wchar or long */
      char suppress;              /* 0 is not have %* in format */
  } SecScanSpec;
  
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
  #define SECUREC_INIT_NUMBER_SPEC { 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0 }
  #else
  #define SECUREC_INIT_NUMBER_SPEC { 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0 }
  #endif
  
  #ifdef SECUREC_FOR_WCHAR
  #define SECUREC_GETC fgetwc
  #define SECUREC_UN_GETC ungetwc
  #define SECUREC_CHAR_MASK 0xffff
  #else
  #define SECUREC_GETC fgetc
  #define SECUREC_UN_GETC ungetc
  #define SECUREC_CHAR_MASK 0xff
  #endif
  
  /* Record a flag for each bit */
  #define SECUREC_BRACKET_INDEX(x)  ((unsigned int)(x) >> 3)
  #define SECUREC_BRACKET_VALUE(x)  ((unsigned char)(1 << ((unsigned int)(x) & 7)))
  
  /*
   * Set char in %[xxx] into table, only supports  wide characters with a maximum length of two bytes
   */
  SECUREC_INLINE void SecBracketSetBit(unsigned char *table, SecUnsignedChar ch)
  {
      unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK));
      unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK));
      /* Do not use   |=   optimize this code, it will cause compiling warning */
      table[tableIndex] = (unsigned char)(table[tableIndex] | tableValue);
  }
  
  /*
   * Determine whether the expression can be satisfied
   */
  SECUREC_INLINE int SecCanInputForBracket(int convChr, SecInt ch, const SecBracketTable *bracketTable)
  {
      unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK));
      unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK));
  #ifdef SECUREC_FOR_WCHAR
      return (convChr == SECUREC_BRACE && bracketTable->table != NULL &&
          ((bracketTable->table[tableIndex] ^ bracketTable->mask) & tableValue));
  #else
      return (convChr == SECUREC_BRACE && ((bracketTable->table[tableIndex] ^ bracketTable->mask) & tableValue));
  #endif
  }
  
  /*
   * String input ends when blank character is encountered
   */
  SECUREC_INLINE int SecCanInputString(int convChr, SecInt ch)
  {
      return ((convChr) == SECUREC_CHAR('s') &&
          (!((ch) >= SECUREC_CHAR('\t') && (ch) <= SECUREC_CHAR('\r')) && (ch) != SECUREC_CHAR(' ')));
  }
  
  /*
   * Can input a character when format is %c
   */
  SECUREC_INLINE int SecCanInputCharacter(int convChr)
  {
      return (convChr == SECUREC_CHAR('c'));
  }
  
  /*
   * Determine if it is a 64-bit pointer  function
   * Return 0 is not ,1 is 64bit pointer
   */
  SECUREC_INLINE int SecIs64BitPtr(size_t sizeOfVoidStar)
  {
      /* Point size is 4 or 8 , Under the 64 bit system, the value not 0 */
      /* To clear e778 */
      if ((sizeOfVoidStar & sizeof(SecInt64)) != 0) {
          return 1;
      }
      return 0;
  }
  SECUREC_INLINE int SecIsDigit(SecInt ch);
  SECUREC_INLINE int SecIsXdigit(SecInt ch);
  SECUREC_INLINE int SecIsSpace(SecInt ch);
  SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter);
  SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter);
  SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter);
  
  #if SECUREC_ENABLE_SCANF_FLOAT
  
  /*
   * Convert a floating point string to a floating point number
   */
  SECUREC_INLINE void SecAssignFloat(const char *floatStr, int numberWidth, void *argPtr)
  {
      char *endPtr = NULL;
      double d;
  #if SECUREC_SUPPORT_STRTOLD
      if (numberWidth == SECUREC_NUM_WIDTH_LONG_LONG) {
          long double d2 = strtold(floatStr, &endPtr);
          *(long double UNALIGNED *)(argPtr) = d2;
          return;
      }
  #endif
      d = strtod(floatStr, &endPtr);
      if (numberWidth > SECUREC_NUM_WIDTH_INT) {
          *(double UNALIGNED *)(argPtr) = (double)d;
      } else {
          *(float UNALIGNED *)(argPtr) = (float)d;
      }
  }
  
  #ifdef SECUREC_FOR_WCHAR
  /*
   * Convert a floating point wchar string to a floating point number
   * Success  ret 0
   */
  SECUREC_INLINE int SecAssignFloatW(const SecFloatSpec *floatSpec, const  SecScanSpec *spec)
  {
      /* Convert float string */
      size_t mbsLen;
      size_t tempFloatStrLen = (size_t)(floatSpec->floatStrTotalLen + 1) * sizeof(wchar_t);
      char *tempFloatStr = (char *)SECUREC_MALLOC(tempFloatStrLen);
  
      if (tempFloatStr == NULL) {
          return -1;
      }
      tempFloatStr[0] = '\0';
      SECUREC_MASK_MSVC_CRT_WARNING
      mbsLen = wcstombs(tempFloatStr, floatSpec->floatStr, tempFloatStrLen - 1);
      SECUREC_END_MASK_MSVC_CRT_WARNING
      /* This condition must satisfy mbsLen is not -1 */
      if (mbsLen < tempFloatStrLen) {
          tempFloatStr[mbsLen] = '\0';
          SecAssignFloat(tempFloatStr, spec->numberWidth, spec->argPtr);
      } else {
          SECUREC_FREE(tempFloatStr);
          return -1;
      }
      SECUREC_FREE(tempFloatStr);
      return 0;
  }
  #endif
  
  /*
   * Init SecFloatSpec befor parse format
   */
  SECUREC_INLINE void SecInitFloatSpec(SecFloatSpec *floatSpec)
  {
      floatSpec->floatStr = floatSpec->buffer;
      floatSpec->allocatedFloatStr = NULL;
      floatSpec->floatStrTotalLen = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]);
      floatSpec->floatStr = floatSpec->buffer;
      floatSpec->floatStrUsedLen = 0;
  }
  
  SECUREC_INLINE void SecFreeFloatSpec(SecFloatSpec *floatSpec, int *doneCount)
  {
       /* LSD 2014.3.6 add, clear the stack data */
      if (memset_s(floatSpec->buffer, sizeof(floatSpec->buffer), 0, sizeof(floatSpec->buffer)) != EOK) {
          *doneCount = 0; /* This code just to meet the coding requirements */
      }
      /* The pFloatStr can be alloced in SecUpdateFloatString function, clear and free it */
      if (floatSpec->allocatedFloatStr != NULL) {
          size_t bufferSize = floatSpec->floatStrTotalLen * sizeof(SecChar);
          if (memset_s(floatSpec->allocatedFloatStr, bufferSize, 0, bufferSize) != EOK) {
              *doneCount = 0; /* This code just to meet the coding requirements */
          }
          SECUREC_FREE(floatSpec->allocatedFloatStr);
          floatSpec->allocatedFloatStr = NULL;
          floatSpec->floatStr = NULL;
      }
  }
  
  /*
   * Splice floating point string
   * Return 0 OK
   */
  SECUREC_INLINE int SecUpdateFloatString(SecChar ch, SecFloatSpec *floatSpec)
  {
      floatSpec->floatStr[floatSpec->floatStrUsedLen++] = ch;
      if (floatSpec->floatStrUsedLen >= floatSpec->floatStrTotalLen) {
          /* Buffer size is len x sizeof(SecChar) */
          size_t oriSize = floatSpec->floatStrTotalLen * sizeof(SecChar);
          /* Add one character to clear tool warning */
          size_t nextSize = (oriSize * 2) + sizeof(SecChar); /* Multiply 2 to extend buffer size */
  
          /* Prevents integer overflow, the maximum length of SECUREC_MAX_WIDTH_LEN is enough */
          if (nextSize <= SECUREC_MAX_WIDTH_LEN) {
              void *nextBuffer = (void *)SECUREC_MALLOC(nextSize);
              if (nextBuffer == NULL) {
                  return -1;
              }
              if (memcpy_s(nextBuffer, nextSize, floatSpec->floatStr, oriSize) != EOK) {
                  SECUREC_FREE(nextBuffer);   /* This is a dead code, just to meet the coding requirements */
                  return -1;
              }
              /* Clear old buffer memory */
              if (memset_s(floatSpec->floatStr, oriSize, 0, oriSize) != EOK) {
                  SECUREC_FREE(nextBuffer);   /* This is a dead code, just to meet the coding requirements */
                  return -1;
              }
              /* Free old allocated buffer */
              if (floatSpec->allocatedFloatStr != NULL) {
                  SECUREC_FREE(floatSpec->allocatedFloatStr);
              }
              floatSpec->allocatedFloatStr = (SecChar *)(nextBuffer);    /* Use to clear free on stack warning */
              floatSpec->floatStr = (SecChar *)(nextBuffer);
              floatSpec->floatStrTotalLen = nextSize / sizeof(SecChar); /* Get buffer total len in character */
              return 0;
          }
          return -1; /* Next size is beyond max */
      }
      return 0;
  }
  
  
  /* Do not use localeconv()->decimal_pointif  onlay support  '.' */
  SECUREC_INLINE int SecIsFloatDecimal(SecChar ch)
  {
      return ((ch) == SECUREC_CHAR('.'));
  }
  
  /*
   * Scan value of exponent.
   * Return 0 OK
   */
  SECUREC_INLINE int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
  {
      spec->ch = SecGetChar(stream, &(spec->charCount));
      if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
          if (spec->ch == SECUREC_CHAR('-') && SecUpdateFloatString((SecChar)'-', floatSpec) != 0) {
              return -1;
          }
          if (spec->width != 0) {
              spec->ch = SecGetChar(stream, &(spec->charCount));
              --spec->width;
          }
      }
  
      while (SecIsDigit(spec->ch) && spec->width-- != 0) {
          if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) {
              return -1;
          }
          spec->ch = SecGetChar(stream, &(spec->charCount));
      }
      return 0;
  }
  
  /*
   * Scan %f.
   * Return 0 OK
   */
  SECUREC_INLINE int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
  {
      int started = -1;
      spec->ch = SecGetChar(stream, &(spec->charCount));
  
      floatSpec->floatStrUsedLen = 0;
      if (spec->ch == SECUREC_CHAR('-')) {
          floatSpec->floatStr[floatSpec->floatStrUsedLen++] = SECUREC_CHAR('-');
          --spec->width;
          spec->ch = SecGetChar(stream, &(spec->charCount));
      } else if (spec->ch == SECUREC_CHAR('+')) {
          --spec->width;
          spec->ch = SecGetChar(stream, &(spec->charCount));
      }
  
      if (spec->widthSet == 0) {    /* Must care width */
          spec->width = -1; /* -1 is unlimited */
      }
  
      /* Now get integral part */
      while (SecIsDigit(spec->ch) && spec->width-- != 0) {
          started = 0;
          /* The ch must be '0' - '9' */
          if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) {
              return -1;
          }
          spec->ch = SecGetChar(stream, &(spec->charCount));
      }
  
      /* Now get fractional part */
      if (SecIsFloatDecimal((SecChar)spec->ch) && spec->width-- != 0) {
          /* Now check for decimal */
          if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) {
              return -1;
          }
          spec->ch = SecGetChar(stream, &(spec->charCount));
          while (SecIsDigit(spec->ch) && spec->width-- != 0) {
              started = 0;
              if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) {
                  return -1;
              }
              spec->ch = SecGetChar(stream, &(spec->charCount));
          }
      }
  
      /* Now get exponent part */
      if (started == 0 && (spec->ch == SECUREC_CHAR('e') || spec->ch == SECUREC_CHAR('E')) && spec->width-- != 0) {
          if (SecUpdateFloatString((SecChar)'e', floatSpec) != 0) {
              return -1;
          }
          if (SecInputFloatE(stream, spec, floatSpec) != 0) {
              return -1;
          }
      }
      /* Un set the last character that is not a floating point number */
      SecUnGetChar(spec->ch, stream, &(spec->charCount));
      /* Make sure  have a string terminator, buffer is large enough */
      floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0');
      return started;
  }
  #endif
  
  #if (!defined(SECUREC_FOR_WCHAR) && SECUREC_HAVE_WCHART && SECUREC_HAVE_MBTOWC) || \
      (!defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION))
  /* LSD only multi-bytes string need isleadbyte() function */
  SECUREC_INLINE int SecIsLeadByte(SecInt ch)
  {
      unsigned int c = (unsigned int)ch;
  #if !(defined(_MSC_VER) || defined(_INC_WCTYPE))
      return (int)(c & 0x80);
  #else
      return (int)isleadbyte((int)(c & 0xff));
  #endif
  }
  #endif
  
  /*
   * Parsing whether it is a wide character
   */
  SECUREC_INLINE void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec)
  {
      if (spec->isWCharOrLong != 0) {
          /* Wide character identifiers have been explicitly set by l or h flag */
          return;
      }
  
      /* Set default flag */
  #if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT)
      spec->isWCharOrLong = 1;  /* On windows wide char version %c %s %[ is wide char */
  #else
      spec->isWCharOrLong = -1; /* On linux all version %c %s %[ is multi char */
  #endif
  
      if (ch == SECUREC_CHAR('C') || ch == SECUREC_CHAR('S')) {
  #if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT)
          spec->isWCharOrLong = -1; /* On windows wide char version %C %S is multi char */
  #else
          spec->isWCharOrLong = 1;  /* On linux all version %C %S is wide char */
  #endif
      }
  
      return;
  }
  /*
   * Decode  %l %ll
   */
  SECUREC_INLINE void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec)
  {
      const SecUnsignedChar *fmt = *format;
      if (*(fmt + 1) == SECUREC_CHAR('l')) {
          spec->isInt64Arg = 1;
          spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
          ++fmt;
      } else {
          spec->numberWidth = SECUREC_NUM_WIDTH_LONG;
  #if defined(SECUREC_ON_64BITS) && !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
          /* On window 64 system sizeof long is 32bit */
          spec->isInt64Arg = 1;
  #endif
          spec->isWCharOrLong = 1;
      }
      *format = fmt;
  }
  
  /*
   * Decode  %I %I43 %I64 %Id %Ii %Io ...
   * Set finishFlag to  1  finish Flag
   */
  SECUREC_INLINE void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
  {
      const SecUnsignedChar *fmt = *format;
      if ((*(fmt + 1) == SECUREC_CHAR('6')) &&
          (*(fmt + 2) == SECUREC_CHAR('4'))) { /* Offset 2 for I64 */
          spec->isInt64Arg = 1;
          *format = *format + 2; /* Add 2 to skip I64 point to '4' next loop will inc */
      } else if ((*(fmt + 1) == SECUREC_CHAR('3')) &&
                  (*(fmt + 2) == SECUREC_CHAR('2'))) { /* Offset 2 for I32 */
          *format = *format + 2; /* Add 2 to skip I32 point to '2' next loop will inc */
      } else if ((*(fmt + 1) == SECUREC_CHAR('d')) ||
                  (*(fmt + 1) == SECUREC_CHAR('i')) ||
                  (*(fmt + 1) == SECUREC_CHAR('o')) ||
                  (*(fmt + 1) == SECUREC_CHAR('x')) ||
                  (*(fmt + 1) == SECUREC_CHAR('X'))) {
          spec->isInt64Arg = SecIs64BitPtr(sizeof(void *));
      } else {
          /* For %I */
          spec->isInt64Arg = SecIs64BitPtr(sizeof(void *));
          *finishFlag = 1;
      }
  }
  
  SECUREC_INLINE int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec)
  {
      const SecUnsignedChar *fmt = *format;
      while (SecIsDigit((SecInt)(int)(*fmt))) {
          spec->widthSet = 1;
          if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(spec->width)) {
              return -1;
          }
          spec->width = (int)SECUREC_MUL_TEN((unsigned int)spec->width) + (unsigned char)(*fmt - SECUREC_CHAR('0'));
          ++fmt;
      }
      *format = fmt;
      return 0;
  }
  
  /*
   * Init default flags for each format. do not init ch this variable is context-dependent
   */
  SECUREC_INLINE void SecSetDefaultScanSpec(SecScanSpec *spec)
  {
      /* The ch and charCount member variables cannot be initialized here */
      spec->number64 = 0;
      spec->number = 0;
      spec->numberWidth = SECUREC_NUM_WIDTH_INT;    /* 0 = SHORT, 1 = int, > 1  long or L_DOUBLE */
      spec->isInt64Arg = 0;                         /* 1 for 64-bit integer, 0 otherwise */
      spec->negative = 0;
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      spec->beyondMax = 0;
  #endif
      spec->argPtr = NULL;
      spec->arrayWidth = 0;
      spec->width = 0;
      spec->widthSet = 0;
      spec->convChr = 0;
      spec->oriConvChr = 0;
      spec->isWCharOrLong = 0;
      spec->suppress = 0;
  }
  
  /*
   * Decode qualifier %I %L %h ...
   * Set finishFlag to  1  finish Flag
   */
  SECUREC_INLINE void  SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
  {
      switch ((int)(unsigned char)(**(format))) {
          case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */
          case SECUREC_CHAR('N'):
              break;
          case SECUREC_CHAR('h'):
              --spec->numberWidth; /* The h for SHORT , hh for CHAR */
              spec->isWCharOrLong = -1;
              break;
  #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
          case SECUREC_CHAR('j'):
              spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;  /* For intmax_t or uintmax_t */
              spec->isInt64Arg = 1;
              break;
          case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */
  #endif
  #if SECUREC_IN_KERNEL
          case SECUREC_CHAR('Z'): /* fall-through */ /* FALLTHRU */
  #endif
          case SECUREC_CHAR('z'):
  #ifdef SECUREC_ON_64BITS
              spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
              spec->isInt64Arg = 1;
  #else
              spec->numberWidth = SECUREC_NUM_WIDTH_LONG;
  #endif
              break;
          case SECUREC_CHAR('L'):    /* For long double */ /* fall-through */ /* FALLTHRU */
          case SECUREC_CHAR('q'):
              spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
              spec->isInt64Arg = 1;
              break;
          case SECUREC_CHAR('l'):
              SecDecodeScanQualifierL(format, spec);
              break;
          case SECUREC_CHAR('w'):
              spec->isWCharOrLong = 1;
              break;
          case SECUREC_CHAR('*'):
              spec->suppress = 1;
              break;
          case SECUREC_CHAR('I'):
              SecDecodeScanQualifierI(format, spec, finishFlag);
              break;
          default:
              *finishFlag = 1;
              break;
      }
  
  }
  /*
   * Decode width and qualifier in format
   */
  SECUREC_INLINE int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec)
  {
      const SecUnsignedChar *fmt = *format;
      int finishFlag = 0;
  
      do {
          ++fmt; /*  First skip % , next  seek fmt */
          /* May %*6d , so put it inside the loop */
          if (SecDecodeScanWidth(&fmt, spec) != 0) {
              return -1;
          }
          SecDecodeScanQualifier(&fmt, spec, &finishFlag);
      } while (finishFlag == 0);
      *format = fmt;
      return 0;
  }
  
  /*
   * Judging whether a zeroing buffer is needed according to different formats
   */
  SECUREC_INLINE int SecDecodeClearFormat(const SecUnsignedChar *format, int *convChr)
  {
      const SecUnsignedChar *fmt = format;
      /* To lowercase */
      int ch = (unsigned char)(*fmt) | (SECUREC_CHAR('a') - SECUREC_CHAR('A'));
      if (!(ch == SECUREC_CHAR('c') || ch == SECUREC_CHAR('s') || ch == SECUREC_BRACE)) {
          return -1;     /* First argument is not a string type */
      }
      if (ch == SECUREC_BRACE) {
  #if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
          if (*fmt == SECUREC_CHAR('{')) {
              return -1;
          }
  #endif
          ++fmt;
          if (*fmt == SECUREC_CHAR('^')) {
              ++fmt;
          }
          if (*fmt == SECUREC_CHAR(']')) {
              ++fmt;
          }
          while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
              ++fmt;
          }
          if (*fmt == SECUREC_CHAR('\0')) {
              return -1; /* Trunc'd format string */
          }
      }
      *convChr = ch;
      return 0;
  }
  
  /*
   * Add L'\0' for wchar string , add '\0' for char string
   */
  SECUREC_INLINE void SecAddEndingZero(void *ptr, const SecScanSpec *spec)
  {
      if (spec->suppress == 0) {
          *(char *)ptr = '\0';
  #if SECUREC_HAVE_WCHART
          if (spec->isWCharOrLong > 0) {
              *(wchar_t UNALIGNED *)ptr = L'\0';
          }
  #endif
      }
  }
  
  #ifdef SECUREC_FOR_WCHAR
  /*
   *  Clean up the first %s %c buffer to zero for wchar version
   */
  void SecClearDestBufW(const wchar_t *buffer, const wchar_t *format, va_list argList)
  #else
  /*
   *  Clean up the first %s %c buffer to zero for char version
   */
  void SecClearDestBuf(const char *buffer, const char *format, va_list argList)
  #endif
  {
  
      va_list argListSave;        /* Backup for argList value, this variable don't need initialized */
      SecScanSpec spec;
      int convChr = 0;
      const SecUnsignedChar *fmt = (const SecUnsignedChar *)format;
      if (fmt == NULL) {
          return;
      }
  
      /* Find first % */
      while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR('%')) {
          ++fmt;
      }
      if (*fmt == SECUREC_CHAR('\0')) {
          return;
      }
  
      SecSetDefaultScanSpec(&spec);
      if (SecDecodeScanFlag(&fmt, &spec) != 0) {
          return;
      }
  
      /* Update wchar flag for %S %C */
      SecUpdateWcharFlagByType(*fmt, &spec);
  
      if (spec.suppress != 0 || SecDecodeClearFormat(fmt, &convChr) != 0) {
          return;
      }
  
      if (buffer != NULL && *buffer != SECUREC_CHAR('\0') && convChr != SECUREC_CHAR('s')) {
          /*
           * When buffer not empty just clear %s.
           * Example call sscanf by  argment of (" \n", "%s", s, sizeof(s))
           */
          return;
      }
      (void)memset(&argListSave, 0, sizeof(va_list)); /* To clear e530 argListSave not initialized */
  #if defined(va_copy)
      va_copy(argListSave, argList);
  #elif defined(__va_copy)        /* For vxworks */
      __va_copy(argListSave, argList);
  #else
      argListSave = argList;
  #endif
      do {
          void *argPtr = (void *)va_arg(argListSave, void *);
          /* Get the next argument - size of the array in characters */
          size_t arrayWidth = ((size_t)(va_arg(argListSave, size_t))) & 0xFFFFFFFFUL;
          va_end(argListSave);
          /* To clear e438 last value assigned not used , the compiler will optimize this code */
          (void)argListSave;
          /* There is no need to judge the upper limit */
          if (arrayWidth == 0 || argPtr == NULL) {
              return;
          }
  
          /* Clear one char */
          SecAddEndingZero(argPtr, &spec);
      } SECUREC_WHILE_ZERO;
      return;
  
  }
  
  /*
   *  Assign number  to output buffer
   */
  SECUREC_INLINE void SecAssignNumber(const SecScanSpec *spec)
  {
      void *argPtr = spec->argPtr;
      if (spec->isInt64Arg != 0) {
  #if defined(SECUREC_VXWORKS_PLATFORM)
  #if defined(SECUREC_VXWORKS_PLATFORM_COMP)
          *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64);
  #else
          /* Take number64 as unsigned number unsigned to int clear Compile warning */
          *(SecInt64 UNALIGNED *)argPtr = *(SecUnsignedInt64 *)(&(spec->number64));
  #endif
  #else
          /* Take number64 as unsigned number */
          *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64);
  #endif
          return;
      }
      if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) {
          /* Take number as unsigned number */
          *(long UNALIGNED *)argPtr = (long)(spec->number);
      } else if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
          *(int UNALIGNED *)argPtr = (int)(spec->number);
      } else if (spec->numberWidth == SECUREC_NUM_WIDTH_SHORT) {
          /* Take number as unsigned number */
          *(short UNALIGNED *)argPtr = (short)(spec->number);
      } else {  /* < 0 for hh format modifier */
          /* Take number as unsigned number */
          *(char UNALIGNED *)argPtr = (char)(spec->number);
      }
  }
  
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
  /*
   *  Judge the long bit width
   */
  SECUREC_INLINE int SecIsLongBitEqual(int bitNum)
  {
      return (unsigned int)bitNum == SECUREC_LONG_BIT_NUM;
  }
  #endif
  
  /*
   * Convert hexadecimal characters to decimal value
   */
  SECUREC_INLINE int SecHexValueOfChar(SecInt ch)
  {
      /* Use isdigt Causing tool false alarms */
      return (int)((ch >= '0' && ch <= '9') ? ((unsigned char)ch - '0') :
              ((((unsigned char)ch | (unsigned char)('a' - 'A')) - ('a')) + 10)); /* Adding 10 is to hex value */
  }
  
  /*
   * Parse decimal character to integer for 32bit .
   */
  static void SecDecodeNumberDecimal(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      unsigned long decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN;
  #ifdef SECUREC_ON_64BITS
      if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
          decimalEdge = (unsigned long)SECUREC_MAX_64BITS_VALUE_DIV_TEN;
      }
  #endif
      if (spec->number > decimalEdge) {
          spec->beyondMax = 1;
      }
  #endif
      spec->number = SECUREC_MUL_TEN(spec->number);
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (spec->number == SECUREC_MUL_TEN(decimalEdge)) {
          SecUnsignedInt64 number64As = (unsigned long)SECUREC_MAX_64BITS_VALUE - spec->number;
          if (number64As < (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'))) {
              spec->beyondMax = 1;
          }
      }
  #endif
      spec->number += (unsigned long)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'));
  
  }
  
  
  /*
   * Parse Hex character to integer for 32bit .
   */
  static void SecDecodeNumberHex(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (SECUREC_LONG_HEX_BEYOND_MAX(spec->number)) {
          spec->beyondMax = 1;
      }
  #endif
      spec->number = SECUREC_MUL_SIXTEEN(spec->number);
      spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(spec->ch);
  }
  
  
  /*
   * Parse Octal character to integer for 32bit .
   */
  static void SecDecodeNumberOctal(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (SECUREC_LONG_OCTAL_BEYOND_MAX(spec->number)) {
          spec->beyondMax = 1;
      }
  #endif
      spec->number = SECUREC_MUL_EIGHT(spec->number);
      spec->number += (unsigned long)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'));
  }
  
  
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
  /* Compatible with integer negative values other than int */
  SECUREC_INLINE void SecFinishNumberNegativeOther(SecScanSpec *spec)
  {
      if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) {
          if (spec->number > SECUREC_MIN_LONG_NEG_VALUE) {
              spec->number = SECUREC_MIN_LONG_NEG_VALUE;
          } else {
              spec->number = (unsigned long)(-(long)spec->number);
          }
          if (spec->beyondMax != 0) {
              if (spec->numberWidth < SECUREC_NUM_WIDTH_INT) {
                  spec->number = 0;
              } else if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG) {
                  spec->number = SECUREC_MIN_LONG_NEG_VALUE;
              }
          }
      } else { /* For o, u, x, X, p */
          spec->number = (unsigned long)(-(long)spec->number);
          if (spec->beyondMax != 0) {
              spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
          }
      }
  }
  /* Compatible processing of integer negative numbers */
  SECUREC_INLINE void SecFinishNumberNegativeInt(SecScanSpec *spec)
  {
      if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) {
  #ifdef SECUREC_ON_64BITS
          if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
              if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) {
                  spec->number = 0;
              } else {
                  spec->number = (unsigned int)(-(int)spec->number);
              }
          }
  #else
          if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
              if ((spec->number > SECUREC_MIN_32BITS_NEG_VALUE)) {
                  spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
              } else {
                  spec->number = (unsigned int)(-(int)spec->number);
              }
          }
  #endif
          if (spec->beyondMax != 0) {
  #ifdef SECUREC_ON_64BITS
              if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
                  spec->number = 0;
              }
  #else
              if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
                  spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
              }
  #endif
          }
      } else {            /* For o, u, x, X ,p */
  #ifdef SECUREC_ON_64BITS
          if (spec->number > SECUREC_MAX_32BITS_VALUE_INC) {
              spec->number = SECUREC_MAX_32BITS_VALUE;
          } else {
              spec->number = (unsigned int)(-(int)spec->number);
          }
  #else
          spec->number = (unsigned int)(-(int)spec->number);
  #endif
          if (spec->beyondMax != 0) {
              spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
          }
      }
  }
  
  /* Compatible with integer positive values other than int */
  SECUREC_INLINE void SecFinishNumberPositiveOther(SecScanSpec *spec)
  {
      if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) {
          if (spec->number > SECUREC_MAX_LONG_POS_VALUE) {
              spec->number = SECUREC_MAX_LONG_POS_VALUE;
          }
          if ((spec->beyondMax != 0 && spec->numberWidth < SECUREC_NUM_WIDTH_INT)) {
              spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
          }
          if (spec->beyondMax != 0 && spec->numberWidth == SECUREC_NUM_WIDTH_LONG) {
              spec->number = SECUREC_MAX_LONG_POS_VALUE;
          }
      } else {
          if (spec->beyondMax != 0) {
              spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
          }
      }
  }
  
  /* Compatible processing of integer positive numbers */
  SECUREC_INLINE void SecFinishNumberPositiveInt(SecScanSpec *spec)
  {
      if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) {
  #ifdef SECUREC_ON_64BITS
          if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
              if (spec->number > SECUREC_MAX_64BITS_POS_VALUE) {
                  spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
              }
          }
          if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
              spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
          }
  #else
          if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
              if (spec->number > SECUREC_MAX_32BITS_POS_VALUE) {
                  spec->number = SECUREC_MAX_32BITS_POS_VALUE;
              }
          }
          if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
              spec->number = SECUREC_MAX_32BITS_POS_VALUE;
          }
  #endif
      } else {            /* For o,u,x,X,p */
          if (spec->beyondMax != 0) {
              spec->number = SECUREC_MAX_32BITS_VALUE;
          }
      }
  }
  
  #endif
  
  /*
   * Parse decimal character to integer for 64bit .
   */
  static void SecDecodeNumber64Decimal(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (spec->number64 > SECUREC_MAX_64BITS_VALUE_DIV_TEN) {
          spec->beyondMax = 1;
      }
  #endif
      spec->number64 = SECUREC_MUL_TEN(spec->number64);
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (spec->number64 == SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT) {
          SecUnsignedInt64 number64As = (SecUnsignedInt64)SECUREC_MAX_64BITS_VALUE - spec->number64;
          if (number64As < (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'))) {
              spec->beyondMax = 1;
          }
      }
  #endif
      spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'));
  }
  
  /*
   * Parse Hex character to integer for 64bit .
   */
  static void SecDecodeNumber64Hex(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (SECUREC_QWORD_HEX_BEYOND_MAX(spec->number64)) {
          spec->beyondMax = 1;
      }
  #endif
      spec->number64 = SECUREC_MUL_SIXTEEN(spec->number64);
      spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(spec->ch);
  
  }
  
  /*
   * Parse Octal character to integer for 64bit .
   */
  static void SecDecodeNumber64Octal(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (SECUREC_QWORD_OCTAL_BEYOND_MAX(spec->number64)) {
          spec->beyondMax = 1;
      }
  #endif
      spec->number64 = SECUREC_MUL_EIGHT(spec->number64);
      spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'));
  }
  
  #define SECUREC_DECODE_NUMBER_FUNC_NUM 2
  /* Function name cannot add address symbol, causing 546 alarm */
  static void (*g_secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \
      { SecDecodeNumberHex, SecDecodeNumber64Hex };
  static void (*g_secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \
      { SecDecodeNumberOctal, SecDecodeNumber64Octal };
  static void (*g_secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \
      { SecDecodeNumberDecimal, SecDecodeNumber64Decimal };
  
  /*
   * Parse 64-bit integer formatted input, return 0 when ch is a number.
   */
  SECUREC_INLINE int SecDecodeNumber(SecScanSpec *spec)
  {
      if (spec->convChr == SECUREC_CHAR('x') || spec->convChr == SECUREC_CHAR('p')) {
          if (SecIsXdigit(spec->ch)) {
              (*g_secDecodeNumberHex[spec->isInt64Arg])(spec);
          } else {
              return -1;
          }
          return 0;
      }
      if (!(SecIsDigit(spec->ch))) {
          return -1;
      }
      if (spec->convChr == SECUREC_CHAR('o')) {
          if (spec->ch < SECUREC_CHAR('8')) {
              (*g_secDecodeNumberOctal[spec->isInt64Arg])(spec);
          } else {
              return -1;
          }
      } else { /* The convChr is 'd' */
          (*g_secDecodeNumberDecimal[spec->isInt64Arg])(spec);
      }
      return 0;
  }
  
  
  /*
   * Complete the final 32-bit integer formatted input
   */
  static void SecFinishNumber(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (spec->negative != 0) {
          if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
              SecFinishNumberNegativeInt(spec);
          } else {
              SecFinishNumberNegativeOther(spec);
          }
      } else {
          if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
              SecFinishNumberPositiveInt(spec);
          } else {
              SecFinishNumberPositiveOther(spec);
          }
      }
  #else
      if (spec->negative != 0) {
  #if defined(__hpux)
          if (spec->oriConvChr != SECUREC_CHAR('p')) {
              spec->number = (unsigned long)(-(long)spec->number);
          }
  #else
          spec->number = (unsigned long)(-(long)spec->number);
  #endif
      }
  #endif
      return;
  }
  
  /*
   * Complete the final 64-bit integer formatted input
   */
  static void SecFinishNumber64(SecScanSpec *spec)
  {
  #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
      if (spec->negative != 0) {
          if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) {
              if (spec->number64 > SECUREC_MIN_64BITS_NEG_VALUE) {
                  spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
              } else {
                  spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
              }
              if (spec->beyondMax != 0) {
                  spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
              }
          } else {                /* For o, u, x, X, p */
              spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
              if (spec->beyondMax != 0) {
                  spec->number64 = SECUREC_MAX_64BITS_VALUE;
              }
          }
      } else {
          if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) {
              if (spec->number64 > SECUREC_MAX_64BITS_POS_VALUE) {
                  spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
              }
              if (spec->beyondMax != 0) {
                  spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
              }
          } else {
              if (spec->beyondMax != 0) {
                  spec->number64 = SECUREC_MAX_64BITS_VALUE;
              }
          }
      }
  #else
      if (spec->negative != 0) {
  #if defined(__hpux)
          if (spec->oriConvChr != SECUREC_CHAR('p')) {
              spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
          }
  #else
          spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
  #endif
      }
  #endif
      return;
  }
  static void (*g_secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \
      { SecFinishNumber, SecFinishNumber64 };
  
  #if SECUREC_ENABLE_SCANF_FILE
  
  /*
   *  Adjust the pointer position of the file stream
   */
  SECUREC_INLINE void SecSeekStream(SecFileStream *stream)
  {
      if ((stream->count <= 0) && feof(stream->pf)) {
          /* File pointer at the end of file, don't need to seek back */
          stream->base[0] = '\0';
          return;
      }
      /* LSD seek to original position, bug fix 2014 1 21 */
      if (fseek(stream->pf, stream->oriFilePos, SEEK_SET)) {
          /* Seek failed, ignore it */
          stream->oriFilePos = 0;
          return;
      }
  
      if (stream->fileRealRead > 0) { /* LSD bug fix. when file reach to EOF, don't seek back */
  #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
          int loops;
          for (loops = 0; loops < (stream->fileRealRead / SECUREC_BUFFERED_BLOK_SIZE); ++loops) {
              if (fread(stream->base, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE,
                  stream->pf) != SECUREC_BUFFERED_BLOK_SIZE) {
                  break;
              }
          }
          if ((stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE) != 0) {
              size_t len = fread(stream->base, (size_t)((unsigned int)stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE),
                                 (size_t)1, stream->pf);
              if ((len == 1 || len == 0) && (ftell(stream->pf) < stream->oriFilePos + stream->fileRealRead)) {
                  (void)fseek(stream->pf, stream->oriFilePos + stream->fileRealRead, SEEK_SET);
              }
          }
  
  #else
          /* On linux like system */
          if (fseek(stream->pf, stream->oriFilePos + stream->fileRealRead, SEEK_SET)) {
              /* Seek failed, ignore it */
              stream->oriFilePos = 0;
          }
  #endif
      }
  
      return;
  }
  
  /*
   *  Adjust the pointer position of the file stream and free memory
   */
  SECUREC_INLINE void SecAdjustStream(SecFileStream *stream)
  {
      if (stream != NULL && (stream->flag & SECUREC_FILE_STREAM_FLAG) && stream->base != NULL) {
          SecSeekStream(stream);
          SECUREC_FREE(stream->base);
          stream->base = NULL;
      }
      return;
  }
  #endif
  
  SECUREC_INLINE void SecSkipSpaceFormat(const SecUnsignedChar **format)
  {
      const SecUnsignedChar *fmt = *format;
      while (SecIsSpace((SecInt)(int)(*fmt))) {
          ++fmt;
      }
      *format = fmt;
  }
  
  #if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)
  /*
   * Handling multi-character characters
   */
  SECUREC_INLINE int SecDecodeLeadByte(SecScanSpec *spec,
      const SecUnsignedChar **format, SecFileStream *stream, int *counter)
  {
  #if SECUREC_HAVE_MBTOWC
      const SecUnsignedChar *fmt = *format;
      int ch1 = (int)spec->ch;
      int ch2 = SecGetChar(stream, counter);
      spec->ch = (SecInt)ch2;
      if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch2) {
          /* LSD in console mode, ungetc twice may cause problem */
          SecUnGetChar(ch2, stream, counter);
          SecUnGetChar(ch1, stream, counter);
          return -1;
      }
      ++fmt;
      if (MB_CUR_MAX >= SECUREC_UTF8_BOM_HEADER_SIZE &&
          (((unsigned char)ch1 & SECUREC_UTF8_LEAD_1ST) == SECUREC_UTF8_LEAD_1ST) &&
          (((unsigned char)ch2 & SECUREC_UTF8_LEAD_2ND) == SECUREC_UTF8_LEAD_2ND)) {
          /* This char is very likely to be a UTF-8 char */
          wchar_t tempWChar;
          char temp[SECUREC_MULTI_BYTE_MAX_LEN];
          int ch3 = (int)SecGetChar(stream, counter);
          spec->ch = (SecInt)ch3;
          temp[0] = (char)ch1;
          temp[1] = (char)ch2; /* 1 index of second character */
          temp[2] = (char)ch3; /* 2 index of third character */
          temp[3] = '\0';      /* 3 of string terminator position */
  
          if (mbtowc(&tempWChar, temp, sizeof(temp)) > 0) {
              /* Succeed */
              if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch3) {
                  SecUnGetChar(ch3, stream, counter);
                  return -1;
              }
              ++fmt;
              *counter = *counter - 1;
          } else {
              SecUnGetChar(ch3, stream, counter);
          }
      }
      *counter = *counter - 1;    /* Only count as one character read */
      *format = fmt;
      return 0;
  #else
      SecUnGetChar(spec->ch, stream, counter);
      (void)format; /* To clear e438 last value assigned not used , the compiler will optimize this code */
      return -1;
  #endif
  }
  #endif
  
  /*
   *  Resolving sequence of characters from %[ format, format wile point to ']'
   */
  SECUREC_INLINE int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable)
  {
      const SecUnsignedChar *fmt = *format;
      SecUnsignedChar prevChar = 0;
      SecUnsignedChar last = 0;
  #if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
      if (*fmt == SECUREC_CHAR('{')) {
          return -1;
      }
  #endif
      /* For building "table" data */
      ++fmt; /* Skip [ */
      bracketTable->mask = 0;
      if (*fmt == SECUREC_CHAR('^')) {
          ++fmt;
          bracketTable->mask = (unsigned char)0xff;
      }
      if (*fmt == SECUREC_CHAR(']')) {
          prevChar = SECUREC_CHAR(']');
          ++fmt;
          SecBracketSetBit(bracketTable->table, SECUREC_CHAR(']'));
      }
      while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
          SecUnsignedChar expCh = *(fmt++);
          if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) {
              /* Normal character */
              prevChar = expCh;
              SecBracketSetBit(bracketTable->table, expCh);
          } else {
              /* For %[a-z] */
              expCh = *(fmt++);   /* Get end of range */
              if (prevChar < expCh) { /* %[a-z] */
                  last = expCh;
              } else {
                  prevChar = expCh;
  #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
                  /* For %[z-a] */
                  last = prevChar;
  #else
                  SecBracketSetBit(bracketTable->table, SECUREC_CHAR('-'));
                  SecBracketSetBit(bracketTable->table, expCh);
                  continue;
  #endif
              }
              /* Format %[a-\xff] last is 0xFF, condition (rnch <= last) cause dead loop */
              for (expCh = prevChar; expCh < last; ++expCh) {
                  SecBracketSetBit(bracketTable->table, expCh);
              }
              SecBracketSetBit(bracketTable->table, last);
              prevChar = 0;
          }
      }
      *format = fmt;
      return 0;
  }
  
  #ifdef SECUREC_FOR_WCHAR
  SECUREC_INLINE int SecInputForWchar(SecScanSpec *spec)
  {
      void *endPtr = spec->argPtr;
      if (spec->isWCharOrLong > 0) {
          *(wchar_t UNALIGNED *)endPtr = (wchar_t)spec->ch;
          endPtr = (wchar_t *)endPtr + 1;
          --spec->arrayWidth;
      } else {
  #if SECUREC_HAVE_WCTOMB
          int temp;
          char tmpBuf[SECUREC_MB_LEN + 1];
          SECUREC_MASK_MSVC_CRT_WARNING temp = wctomb(tmpBuf, (wchar_t)spec->ch);
          SECUREC_END_MASK_MSVC_CRT_WARNING
          if (temp <= 0 || (size_t)(unsigned int)temp > sizeof(tmpBuf)) {
              /* If wctomb  error, then ignore character */
              return 0;
          }
          if (((size_t)(unsigned int)temp) > spec->arrayWidth) {
              return -1;
          }
          if (memcpy_s(endPtr, spec->arrayWidth, tmpBuf, (size_t)(unsigned int)temp) != EOK) {
              return -1;
          }
          endPtr = (char *)endPtr + temp;
          spec->arrayWidth -= (size_t)(unsigned int)temp;
  #else
          return -1;
  #endif
      }
      spec->argPtr = endPtr;
      return 0;
  }
  #endif
  
  #ifndef SECUREC_FOR_WCHAR
  #if SECUREC_HAVE_WCHART
  SECUREC_INLINE wchar_t SecConvertInputCharToWchar(SecScanSpec *spec, SecFileStream *stream)
  {
      wchar_t tempWChar = L'?';   /* Set default char is ? */
  #if SECUREC_HAVE_MBTOWC
      char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1];
      temp[0] = (char)spec->ch;
      temp[1] = '\0';
  #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
      if (SecIsLeadByte(spec->ch)) {
          spec->ch = SecGetChar(stream, &(spec->charCount));
          temp[1] = (char)spec->ch;
          temp[2] = '\0'; /* 2 of string terminator position */
      }
      if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) {
          /* No string termination error for tool */
          tempWChar = L'?';
      }
  #else
      if (SecIsLeadByte(spec->ch)) {
          int convRes = 0;
          int di = 1;
          /* On Linux like system, the string is encoded in UTF-8 */
          while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) {
              spec->ch = SecGetChar(stream, &(spec->charCount));
              temp[di++] = (char)spec->ch;
              temp[di] = '\0';
              convRes = mbtowc(&tempWChar, temp, sizeof(temp));
          }
          if (convRes <= 0) {
              tempWChar = L'?';
          }
      } else {
          if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) {
              tempWChar = L'?';
          }
      }
  #endif
  #else
      (void)spec;      /* To clear e438 last value assigned not used , the compiler will optimize this code */
      (void)stream;    /* To clear e438 last value assigned not used , the compiler will optimize this code */
  #endif /* SECUREC_HAVE_MBTOWC */
  
      return tempWChar;
  }
  #endif /* SECUREC_HAVE_WCHART */
  
  
  SECUREC_INLINE int SecInputForChar(SecScanSpec *spec, SecFileStream *stream)
  {
      void *endPtr = spec->argPtr;
      if (spec->isWCharOrLong > 0) {
  #if SECUREC_HAVE_WCHART
          *(wchar_t UNALIGNED *)endPtr = SecConvertInputCharToWchar(spec, stream);
          endPtr = (wchar_t *)endPtr + 1;
          --spec->arrayWidth;
  #else
      (void)stream;    /* To clear e438 last value assigned not used , the compiler will optimize this code */
      return -1;
  #endif
      } else {
          *(char *)endPtr = (char)spec->ch;
          endPtr = (char *)endPtr + 1;
          --spec->arrayWidth;
      }
      spec->argPtr = endPtr;
      return 0;
  }
  #endif
  
  /*
   * Scan digital part of %d %i %o %u %x %p.
   * Return 0 OK
   */
  SECUREC_INLINE int SecInputNumberDigital(SecFileStream *stream, SecScanSpec *spec)
  {
      int loopFlag = 0;
      int started = -1;
      while (loopFlag == 0) {
          /* Decode ch to number */
          loopFlag = SecDecodeNumber(spec);
          if (loopFlag == 0) {
              started = 0;
              if (spec->widthSet != 0 && --spec->width == 0) {
                  loopFlag = 1;
              } else {
                  spec->ch = SecGetChar(stream, &(spec->charCount));
              }
          } else {
              SecUnGetChar(spec->ch, stream, &(spec->charCount));
          }
      }
      /* Handling integer negative numbers and beyond max */
      (*g_secFinishNumber[spec->isInt64Arg])(spec);
      return started;
  
  }
  
  /*
   * Scan %d %i %o %u %x %p.
   * Return 0 OK
   */
  SECUREC_INLINE int SecInputNumber(SecFileStream *stream, SecScanSpec *spec)
  {
      spec->ch = SecGetChar(stream, &(spec->charCount));
  
      if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
          if (spec->ch == SECUREC_CHAR('-')) {
              spec->negative = 1;
  #if SECUREC_IN_KERNEL
              if (spec->convChr == SECUREC_CHAR('x') ||
                  spec->convChr == SECUREC_CHAR('o') ||
                  spec->convChr == SECUREC_CHAR('u')) {
                  /* In kernel Refuse to enter negative number */
                  return -1;
              }
  #endif
          }
          if (spec->widthSet != 0 && --spec->width == 0) {
              return -1;
          } else {
              spec->ch = SecGetChar(stream, &(spec->charCount));
          }
      }
  
      if (spec->oriConvChr == SECUREC_CHAR('i')) {
          /* The i could be d, o, or x, use d as default */
          spec->convChr = SECUREC_CHAR('d');
      }
  
      if (spec->oriConvChr == SECUREC_CHAR('x') || spec->oriConvChr == SECUREC_CHAR('i')) {
          if (spec->ch != SECUREC_CHAR('0')) {
              /* Scan number */
              return SecInputNumberDigital(stream, spec);
          }
          /* Now input string may be 0x123 or 0X123 or just 0 */
          /* Get next char */
          spec->ch = SecGetChar(stream, &(spec->charCount));
          if ((SecChar)spec->ch == SECUREC_CHAR('x') || (SecChar)spec->ch == SECUREC_CHAR('X')) {
              spec->convChr = SECUREC_CHAR('x');
              spec->ch = SecGetChar(stream, &(spec->charCount));
              /* Length of 0x is 2 */
              if (spec->widthSet != 0 && spec->width <= (1 + 1)) {
                  /* Length not enough for "0x" */
                  return -1;
              }
              spec->width -= 2; /* Subtract 2 for the length of "0x" */
          } else {
              if (spec->oriConvChr != SECUREC_CHAR('x')) {
                  spec->convChr = SECUREC_CHAR('o');
              }
              /* Unset the character after 0 back to stream, input only '0' result is OK */
              SecUnGetChar(spec->ch, stream, &(spec->charCount));
              spec->ch = SECUREC_CHAR('0');
          }
      }
      /* Scan number */
      return SecInputNumberDigital(stream, spec);
  }
  
  /*
   * Scan %c %s %[
   * Return 0 OK
   */
  SECUREC_INLINE int SecInputString(SecFileStream *stream, SecScanSpec *spec,
      const SecBracketTable *bracketTable, int *doneCount)
  {
      void *startPtr = spec->argPtr;
      int suppressed = 0;
      int errNoMem = 0;
  
      while (spec->widthSet == 0 || spec->width-- != 0) {
          spec->ch = SecGetChar(stream, &(spec->charCount));
          /*
           * The char condition or string condition and bracket condition.
           * Only supports wide characters with a maximum length of two bytes
           */
          if (spec->ch != SECUREC_EOF && (SecCanInputCharacter(spec->convChr) ||
              SecCanInputString(spec->convChr, spec->ch) ||
              SecCanInputForBracket(spec->convChr, spec->ch, bracketTable))) {
              if (spec->suppress != 0) {
                  /* Used to identify processed data for %*, use argPtr to identify will cause 613, so use suppressed */
                  suppressed = 1;
                  continue;
              }
              /* Now suppress is not set */
              if (spec->arrayWidth == 0) {
                  errNoMem = 1; /* We have exhausted the user's buffer */
                  break;
              }
  #ifdef SECUREC_FOR_WCHAR
              errNoMem = SecInputForWchar(spec);
  #else
              errNoMem = SecInputForChar(spec, stream);
  #endif
              if (errNoMem != 0) {
                  break;
              }
          } else {
              SecUnGetChar(spec->ch, stream, &(spec->charCount));
              break;
          }
      }
  
      if (errNoMem != 0) {
          /* In case of error, blank out the input buffer */
          SecAddEndingZero(startPtr, spec);
          return -1;
      }
  
      /* No input was scanned */
      if ((spec->suppress != 0 && suppressed == 0) ||
          (spec->suppress == 0 && startPtr == spec->argPtr)) {
          return -1;
      }
  
      if (spec->convChr != 'c') {
          /* Add null-terminate for strings */
          SecAddEndingZero(spec->argPtr, spec);
      }
      if (spec->suppress == 0) {
          *doneCount = *doneCount + 1;
      }
      return 0;
  }
  
  #ifdef SECUREC_FOR_WCHAR
  /*
   * Alloce buffer for wchar version of %[.
   * Return 0 OK
   */
  SECUREC_INLINE int SecAllocBracketTable(SecBracketTable *bracketTable)
  {
      if (bracketTable->table == NULL) {
          /* Table should be freed after use */
          bracketTable->table = (unsigned char *)SECUREC_MALLOC(SECUREC_BRACKET_TABLE_SIZE);
          if (bracketTable->table == NULL) {
              return -1;
          }
      }
      return 0;
  }
  
  /*
   * Free buffer for wchar version of %[
   */
  SECUREC_INLINE void SecFreeBracketTable(SecBracketTable *bracketTable)
  {
      if (bracketTable->table != NULL) {
          SECUREC_FREE(bracketTable->table);
          bracketTable->table = NULL;
      }
  }
  #endif
  
  #ifdef SECUREC_FOR_WCHAR
  /*
   *  Formatting input core functions for wchar version.Called by a function such as vswscanf_s
   */
  int SecInputSW(SecFileStream *stream, const wchar_t *cFormat, va_list argList)
  #else
  /*
   * Formatting input core functions for char version.Called by a function such as vsscanf_s
   */
  int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList)
  #endif
  {
      const SecUnsignedChar *format = (const SecUnsignedChar *)cFormat;
      SecBracketTable bracketTable = SECUREC_INIT_BRACKET_TABLE;
      SecScanSpec spec;
      int doneCount = 0;
      int formatError = 0;
      int paraIsNull = 0;
      int match = 0; /* When % is found , inc this value */
      int errRet = 0;
  #if SECUREC_ENABLE_SCANF_FLOAT
      SecFloatSpec floatSpec;
      SecInitFloatSpec(&floatSpec);
  #endif
      spec.ch = 0;
      spec.charCount = 0;
  
      /* Format must not NULL, use err < 1 to claer 845 */
      while (errRet < 1 && *format != SECUREC_CHAR('\0')) {
          /* Skip space in format and space in input */
          if (SecIsSpace((SecInt)(int)(*format))) {
              /* Read first no space char */
              spec.ch = SecSkipSpaceChar(stream, &(spec.charCount));
              if (spec.ch == SECUREC_EOF) {
                  break;
              }
              /* Put fist no space char backup */
              SecUnGetChar(spec.ch, stream, &(spec.charCount));
              SecSkipSpaceFormat(&format);
              continue;
          }
  
          if (*format != SECUREC_CHAR('%')) {
              spec.ch = SecGetChar(stream, &(spec.charCount));
              if ((int)(*(format++)) != (int)(spec.ch)) {
                  SecUnGetChar(spec.ch, stream, &(spec.charCount));
                  break;
              }
  #if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)
              if (SecIsLeadByte(spec.ch) && SecDecodeLeadByte(&spec, &format, stream) != 0) {
                  break;
              }
  #endif
  
              if (SECUREC_MEET_EOF_BEFORE_NEXT_N(spec.ch, format)) {
                  break;
              }
              continue;
          }
  
          /* Now *format is % */
          /* Set default value for each % */
          SecSetDefaultScanSpec(&spec);
          if (SecDecodeScanFlag(&format, &spec) != 0) {
              formatError = 1;
              ++errRet;
              continue;
          }
          /* Update wchar flag for %S %C */
          SecUpdateWcharFlagByType(*format, &spec);
  
          if (spec.widthSet != 0 && spec.width == 0) {
              /* 0 width in format */
              ++errRet;
              continue;
          }
  
          spec.convChr = (unsigned char)(*format) | (SECUREC_CHAR('a') - SECUREC_CHAR('A')); /* To lowercase */
          spec.oriConvChr = spec.convChr;
  
          if (spec.convChr != SECUREC_CHAR('n')) {
              if (spec.convChr != SECUREC_CHAR('c') && spec.convChr != SECUREC_BRACE) {
                  spec.ch = SecSkipSpaceChar(stream, &(spec.charCount));
              } else {
                  spec.ch = SecGetChar(stream, &(spec.charCount));
              }
              if (spec.ch == SECUREC_EOF) {
                  ++errRet;
                  continue;
              }
          }
  
          /* Now no 0 width in format and get one char from input */
          switch (spec.convChr) {
              case SECUREC_CHAR('c'): /* Also 'C' */
                  /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('s'): /* Also 'S': */
                  /* fall-through */ /* FALLTHRU */
              case SECUREC_BRACE:
                  /* Check dest buffer and size */
                  if (spec.suppress == 0) {
                      spec.argPtr = (void *)va_arg(argList, void *);
                      if (spec.argPtr == NULL) {
                          paraIsNull = 1;
                          ++errRet;
                          continue;
                      }
                      /* Get the next argument - size of the array in characters */
  #ifdef SECUREC_ON_64BITS
                      spec.arrayWidth = ((size_t)(va_arg(argList, size_t))) & 0xFFFFFFFFUL;
  #else /* !SECUREC_ON_64BITS */
                      spec.arrayWidth = (size_t)va_arg(argList, size_t);
  #endif
                      if (SECUREC_ARRAY_WIDTH_IS_WRONG(spec)) {
                          /* Do not clear buffer just go error */
                          ++errRet;
                          continue;
                      }
                      /* One element is needed for '\0' for %s and %[ */
                      if (spec.convChr != SECUREC_CHAR('c')) {
                          --spec.arrayWidth;
                      }
                  } else {
                      /* Set argPtr to  NULL  is necessary, in supress mode we don't use argPtr to store data */
                      spec.argPtr = NULL;
                  }
  
                  if (spec.convChr == 'c') {
                      if (spec.widthSet == 0) {
                          spec.widthSet = 1;
                          spec.width = 1;
                      }
                  } else if (spec.convChr == SECUREC_BRACE) {
                      /* Malloc when first %[ is meet  for wchar version */
  #ifdef SECUREC_FOR_WCHAR
                      if (SecAllocBracketTable(&bracketTable) != 0) {
                          ++errRet;
                          continue;
                      }
  #endif
                      (void)memset(bracketTable.table, 0, (size_t)SECUREC_BRACKET_TABLE_SIZE);
                      if (SecSetupBracketTable(&format, &bracketTable) != 0) {
                          ++errRet;
                          continue;
                      }
  
                      if (*format == SECUREC_CHAR('\0')) {
                          /* Default add string terminator */
                          SecAddEndingZero(spec.argPtr, &spec);
                          ++errRet;
                          /* Truncated format */
                          continue;
                      }
                  }
                  /* Unset last char to stream */
                  SecUnGetChar(spec.ch, stream, &(spec.charCount));
                  /* Set completed.  Now read string */
                  if (SecInputString(stream, &spec, &bracketTable, &doneCount) != 0) {
                      ++errRet;
                      continue;
                  }
                  break;
              case SECUREC_CHAR('p'):
                  /* Make %hp same as %p */
                  spec.numberWidth = SECUREC_NUM_WIDTH_INT;
  #ifdef SECUREC_ON_64BITS
                  spec.isInt64Arg = 1;
  #endif
                  /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('o'):    /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('u'):    /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('d'):    /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('i'):    /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('x'):
                  /* Unset last char to stream */
                  SecUnGetChar(spec.ch, stream, &(spec.charCount));
                  if (SecInputNumber(stream, &spec) != 0) {
                      ++errRet;
                      continue;
                  }
                  if (spec.suppress == 0) {
                      spec.argPtr = (void *)va_arg(argList, void *);
                      if (spec.argPtr == NULL) {
                          paraIsNull = 1;
                          ++errRet;
                          continue;
                      }
                      SecAssignNumber(&spec);
                      ++doneCount;
                  }
                  break;
              case SECUREC_CHAR('n'):    /* Char count */
                  if (spec.suppress == 0) {
                      spec.argPtr = (void *)va_arg(argList, void *);
                      if (spec.argPtr == NULL) {
                          paraIsNull = 1;
                          ++errRet;
                          continue;
                      }
                      spec.number = (unsigned long)(unsigned int)(spec.charCount);
                      spec.isInt64Arg = 0;
                      SecAssignNumber(&spec);
                  }
                  break;
              case SECUREC_CHAR('e'):    /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('f'):    /* fall-through */ /* FALLTHRU */
              case SECUREC_CHAR('g'):    /* Scan a float */
  #if SECUREC_ENABLE_SCANF_FLOAT
                  /* Unset last char to stream */
                  SecUnGetChar(spec.ch, stream, &(spec.charCount));
                  if (SecInputFloat(stream, &spec, &floatSpec) != 0) {
                      ++errRet;
                      continue;
                  }
                  if (spec.suppress == 0) {
                      spec.argPtr = (void *)va_arg(argList, void *);
                      if (spec.argPtr == NULL) {
                          ++errRet;
                          paraIsNull = 1;
                          continue;
                      }
  #ifdef SECUREC_FOR_WCHAR
                      if (SecAssignFloatW(&floatSpec, &spec) != 0) {
                          ++errRet;
                          continue;
                      }
  #else
                      SecAssignFloat(floatSpec.floatStr, spec.numberWidth, spec.argPtr);
  #endif
                      ++doneCount;
                  }
  
                  break;
  #else /* SECUREC_ENABLE_SCANF_FLOAT */
                  ++errRet;
                  continue;
  #endif
              default:
                  if ((int)(*format) != (int)spec.ch) {
                      SecUnGetChar(spec.ch, stream, &(spec.charCount));
                      formatError = 1;
                      ++errRet;
                      continue;
                  } else {
                      --match; /*  Compensate for the self-increment of the following code */
                  }
          }
  
          ++match;
          ++format;
  
          if (SECUREC_MEET_EOF_BEFORE_NEXT_N(spec.ch, format)) {
              break;
          }
      }
  
  #ifdef SECUREC_FOR_WCHAR
      SecFreeBracketTable(&bracketTable);
  #endif
  
  #if SECUREC_ENABLE_SCANF_FLOAT
      SecFreeFloatSpec(&floatSpec, &doneCount);
  #endif
  
  #if SECUREC_ENABLE_SCANF_FILE
      SecAdjustStream(stream);
  #endif
  
      if (spec.ch == SECUREC_EOF) {
          return ((doneCount || match) ? doneCount : SECUREC_SCANF_EINVAL);
      } else if (formatError != 0 || paraIsNull != 0) {
          /* Invalid Input Format or parameter */
          return SECUREC_SCANF_ERROR_PARA;
      }
  
      return doneCount;
  }
  
  #if SECUREC_ENABLE_SCANF_FILE
  
  #if defined(SECUREC_NO_STD_UNGETC)
  /*
   *  Get char  from stream or buffer
   */
  SECUREC_INLINE SecInt SecGetCharFromStream(SecFileStream *stream)
  {
      SecInt ch;
      if (stream->fUnGet == 1) {
          ch = (SecInt) stream->lastChar;
          stream->fUnGet = 0;
      } else {
          ch = SECUREC_GETC(stream->pf);
          stream->lastChar = (unsigned int)ch;
      }
      return ch;
  }
  #else
  /*
   *  Get char from stream use std function
   */
  SECUREC_INLINE SecInt SecGetCharFromStream(const SecFileStream *stream)
  {
      SecInt ch;
      ch = SECUREC_GETC(stream->pf);
      return ch;
  }
  #endif
  
  /*
   * Make data is aligned to SecChar size
   */
  SECUREC_INLINE void SecMakeDataIsAligned(SecFileStream *stream)
  {
      int remainder = stream->count % (int)sizeof(SecChar);
      if (remainder != 0) {
          int needLen = (int)sizeof(SecChar) - remainder;
          int len = (int)fread(stream->base + stream->count, (size_t)1, (size_t)(unsigned int)needLen, stream->pf);
          if (len > 0 && len <= needLen) {
              /* When encountering the end of a file, the read length is less than needLen */
              stream->count += len;
          }
      }
  }
  
  /*
   * Try to read the BOM header, when meet a BOM head, discard it
   */
  SECUREC_INLINE void SecReadAndSkipBomHeader(SecFileStream *stream)
  {
      int bomHeadSize;
  #ifdef SECUREC_FOR_WCHAR
      bomHeadSize = SECUREC_BOM_HEADER_SIZE;
  #else
      bomHeadSize = SECUREC_UTF8_BOM_HEADER_SIZE;
  #endif
      stream->count = (int)fread(stream->base, (size_t)1, (size_t)(unsigned int)bomHeadSize, stream->pf);
      if (stream->count < 0 || stream->count > bomHeadSize) {
          stream->count = 0;
      }
  #ifdef SECUREC_FOR_WCHAR
      if (stream->count >= SECUREC_BOM_HEADER_SIZE &&
          (((unsigned char)(stream->base[0]) == SECUREC_BOM_HEADER_LE_1ST &&
          (unsigned char)(stream->base[1]) == SECUREC_BOM_HEADER_LE_2ST) ||
          ((unsigned char)(stream->base[0]) == SECUREC_BOM_HEADER_BE_1ST &&
          (unsigned char)(stream->base[1]) == SECUREC_BOM_HEADER_BE_2ST))) {
          /* It's BOM header, discard it */
          stream->count = 0;
      }
  #else
      if (stream->count >= SECUREC_UTF8_BOM_HEADER_SIZE &&
          (unsigned char)(stream->base[0]) == SECUREC_UTF8_BOM_HEADER_1ST &&
          (unsigned char)(stream->base[1]) == SECUREC_UTF8_BOM_HEADER_2ND &&
          (unsigned char)(stream->base[2]) == SECUREC_UTF8_BOM_HEADER_3RD) { /* 2 offset of third head character */
          /* It's BOM header, discard it */
          stream->count = 0;
      }
  #endif
      SecMakeDataIsAligned(stream);
  }
  
  /*
   *  Get char  from file stream or buffer
   */
  SECUREC_INLINE SecInt SecGetCharFromFile(SecFileStream *stream)
  {
      SecInt ch;
      if (stream->count == 0) {
          int len;
          /* Load file to buffer */
          if (stream->base == NULL) {
              stream->oriFilePos = ftell(stream->pf);   /* Save original file read position */
              if (stream->oriFilePos == -1) {
                  /* It may be a pipe stream */
                  stream->flag = SECUREC_PIPE_STREAM_FLAG;
                  return SecGetCharFromStream(stream);
              }
              /* Reserve the length of BOM head */
              stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE +
                  SECUREC_BOM_HEADER_SIZE + SECUREC_UTF8_BOM_HEADER_SIZE);
              if (stream->base == NULL) {
                  return SECUREC_EOF;
              }
              /* First read file */
              if (stream->oriFilePos == 0) {
                  SecReadAndSkipBomHeader(stream);
              }
          }
          /* SecReadAndSkipBomHeader has read part of the data, so add offset */
          len = (int)fread(stream->base + stream->count,
              (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf);
          if (len < 0 || len > SECUREC_BUFFERED_BLOK_SIZE) {
              len = 0;
          }
          stream->count += len;
          stream->cur = stream->base;
          stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG;
          stream->base[stream->count] = '\0';   /* For tool Warning string null */
      }
      /* According wchar_t has two bytes */
      stream->count -= (int)sizeof(SecChar);
      ch = (SecInt)((stream->count) >= 0 ? \
                    (SecInt)(SECUREC_CHAR_MASK & \
                    (unsigned int)(int)(*((const SecChar *)(const void *)stream->cur))) : SECUREC_EOF);
      stream->cur += sizeof(SecChar); /* Pointer may be out of bounds, but overread does not occur */
  
      if (ch != SECUREC_EOF && stream->base != NULL) {
          stream->fileRealRead += (int)sizeof(SecChar);
      }
      return ch;
  }
  #endif
  
  /*
   *  Get char  for wchar version
   */
  SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter)
  {
      SecInt ch = SECUREC_EOF;
  #if SECUREC_ENABLE_SCANF_FILE
      if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) > 0) {
          ch = SecGetCharFromStream(stream);
      } else if ((stream->flag & SECUREC_FILE_STREAM_FLAG) > 0) {
          ch = SecGetCharFromFile(stream);
      }
  #endif
      if ((stream->flag & SECUREC_MEM_STR_FLAG) > 0) {
          /* According wchar_t has two bytes */
          stream->count -= (int)sizeof(SecChar);
          ch = (SecInt)((stream->count >= 0) ? \
                        (SecInt)(SECUREC_CHAR_MASK & \
                        (unsigned int)(int)(*((const SecChar *)(const void *)stream->cur))) : SECUREC_EOF);
          stream->cur += sizeof(SecChar);
      }
      *counter = *counter + 1;
      return ch;
  }
  
  /*
   *  Unget Public realizatio char for wchar and char version
   */
  SECUREC_INLINE void SecUnGetCharImpl(SecInt ch, SecFileStream *stream)
  {
      if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) > 0) {
  #if SECUREC_ENABLE_SCANF_FILE
  #if defined(SECUREC_NO_STD_UNGETC)
          stream->lastChar = (unsigned int)ch;
          stream->fUnGet = 1;
  #else
          (void)SECUREC_UN_GETC(ch, stream->pf);
  #endif
  #else
          (void)ch; /* To clear e438 last value assigned not used , the compiler will optimize this code */
  #endif
      } else if ((stream->flag & SECUREC_MEM_STR_FLAG) || (stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) > 0) {
          if (stream->cur > stream->base) {
              stream->cur -= sizeof(SecChar);
              stream->count += (int)sizeof(SecChar);
          }
      }
  #if SECUREC_ENABLE_SCANF_FILE
      if ((stream->flag & SECUREC_FILE_STREAM_FLAG) > 0 && stream->base) {
          stream->fileRealRead -= (int)sizeof(SecChar);
      }
  #endif
  }
  
  /*
   *  Unget char  for char version
   */
  SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter)
  {
      if (ch != SECUREC_EOF) {
          SecUnGetCharImpl(ch, stream);
      }
      *counter = *counter - 1;
  }
  
  /*
   *  Skip space char by isspace
   */
  SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter)
  {
      SecInt ch;
      do {
          ch = SecGetChar(stream, counter);
      } while (ch != SECUREC_EOF && SecIsSpace(ch));
      return ch;
  }
  #endif /* __INPUT_INL__5D13A042_DC3F_4ED9_A8D1_882811274C27 */
  
  