|
- /**
- * Copyright 2020 Huawei Technologies Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #ifndef INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
- #define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
-
- #if SECUREC_IN_KERNEL
- #include <linux/ctype.h>
- #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_BUF_EXT_MUL 2
- #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
- /* 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)))
-
-
- /* 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))
-
- #define SECUREC_LONG_HEX_BEYOND_MAX(number) (((number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0)
- #define SECUREC_LONG_OCTAL_BEYOND_MAX(number) (((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
- #define SECUREC_SCANF_BRACKET_CONDITION(comChr, ch, table, mask) ((comChr) == SECUREC_BRACE && \
- (table) != NULL && \
- (((table)[((unsigned int)(int)(ch) & SECUREC_CHAR_MASK) >> 3] ^ (mask)) & \
- (1 << ((unsigned int)(int)(ch) & 7))))
- #else
- #define SECUREC_SCANF_BRACKET_CONDITION(comChr, ch, table, mask) ((comChr) == SECUREC_BRACE && \
- (((table)[((unsigned char)(ch) & 0xff) >> 3] ^ (mask)) & (1 << ((unsigned char)(ch) & 7))))
- #endif
- #define SECUREC_SCANF_STRING_CONDITION(comChr, ch) ((comChr) == SECUREC_CHAR('s') && \
- (!((ch) >= SECUREC_CHAR('\t') && (ch) <= SECUREC_CHAR('\r')) && (ch) != SECUREC_CHAR(' ')))
-
- /* Do not use |= optimize this code, it will cause compiling warning */
- /* only supports wide characters with a maximum length of two bytes */
- #define SECUREC_BRACKET_SET_BIT(table, ch) do { \
- 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)); \
- (table)[tableIndex] = (unsigned char)((table)[tableIndex] | tableValue); \
- } SECUREC_WHILE_ZERO
-
- #ifdef SECUREC_FOR_WCHAR
- /* table size is 32 x 256 */
- #define SECUREC_BRACKET_TABLE_SIZE 8192
- #define SECUREC_EOF WEOF
- #define SECUREC_MB_LEN 16 /* max. # bytes in multibyte char ,see MB_LEN_MAX */
- /* int to unsigned int clear e571 */
- #define SECUREC_IS_DIGIT(chr) (!((unsigned int)(int)(chr) & 0xff00) && isdigit(((unsigned int)(int)(chr) & 0x00ff)))
- #define SECUREC_IS_XDIGIT(chr) (!((unsigned int)(int)(chr) & 0xff00) && isxdigit(((unsigned int)(int)(chr) & 0x00ff)))
- #define SECUREC_IS_SPACE(chr) iswspace((wint_t)(int)(chr))
- #else
- #define SECUREC_BRACKET_TABLE_SIZE 32
- #define SECUREC_EOF EOF
- #define SECUREC_IS_DIGIT(chr) isdigit((unsigned char)(chr) & 0x00ff)
- #define SECUREC_IS_XDIGIT(chr) isxdigit((unsigned char)(chr) & 0x00ff)
- #define SECUREC_IS_SPACE(chr) isspace((unsigned char)(chr) & 0x00ff)
- #endif
-
-
- static SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter);
- static SecInt SecGetChar(SecFileStream *stream, int *counter);
- static void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter);
-
- 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 floatStrSize; /* tialization 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 {
- 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 comChr; /* Lowercase format conversion characters */
- int oriComChr; /* store number conversion */
- signed char isWChar; /* -1/0 not wchar, 1 for wchar */
- 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
-
- /*
- * Determine if it is a 64-bit pointer function
- * return 0 is not ,1 is 64bit pointer
- */
- static 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;
- }
-
- #if SECUREC_ENABLE_SCANF_FLOAT
-
- /*
- * Convert a floating point string to a floating point number
- */
- static 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
- */
- static int SecAssignFloatW(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
- {
- /* convert float string */
- size_t mbsLen;
- size_t tempFloatStrLen = (size_t)(floatSpec->floatStrSize + 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
- if (mbsLen != (size_t)-1) {
- tempFloatStr[mbsLen] = '\0';
- SecAssignFloat(tempFloatStr, spec->numberWidth, spec->argPtr);
- } else {
- SECUREC_FREE(tempFloatStr);
- return -1;
- }
- SECUREC_FREE(tempFloatStr);
- return 0;
- }
- #endif
- /*
- * Splice floating point string
- * return 0 OK
- */
- static int SecUpdateFloatString(SecChar ch, SecFloatSpec *floatSpec)
- {
- floatSpec->floatStr[floatSpec->floatStrUsedLen++] = ch; /* ch must be '0' - '9' */
- if (floatSpec->floatStrUsedLen < floatSpec->floatStrSize) {
- return 0;
- }
- if (floatSpec->allocatedFloatStr == NULL) {
- /* add 1 to clear ZERO LENGTH ALLOCATIONS warning */
- size_t oriBufSize = floatSpec->floatStrSize* (SECUREC_BUF_EXT_MUL * sizeof(SecChar)) + 1;
- void *tmpPointer = (void *)SECUREC_MALLOC(oriBufSize);
- if (tmpPointer == NULL) {
- return -1;
- }
- if (memcpy_s(tmpPointer, oriBufSize, floatSpec->floatStr, floatSpec->floatStrSize * sizeof(SecChar)) != EOK) {
- SECUREC_FREE(tmpPointer); /* This is a dead code, just to meet the coding requirements */
- return -1;
- }
- floatSpec->floatStr = (SecChar *) (tmpPointer);
- floatSpec->allocatedFloatStr = (SecChar *) (tmpPointer); /* use to clear free on stack warning */
- floatSpec->floatStrSize *= SECUREC_BUF_EXT_MUL; /* this is OK, oriBufSize plus 1 just clear warning */
- return 0;
- } else {
- /* LSD 2014.3.6 fix, replace realloc to malloc to avoid heap injection */
- size_t oriBufSize = floatSpec->floatStrSize * sizeof(SecChar);
- size_t nextSize = (oriBufSize * SECUREC_BUF_EXT_MUL) + 1; /* add 1 to clear satic check tool warning */
- /* Prevents integer overflow when calculating the wide character length.
- * The maximum length of SECUREC_MAX_WIDTH_LEN is enough
- */
- if (nextSize <= SECUREC_MAX_WIDTH_LEN) {
- void *tmpPointer = (void *)SECUREC_MALLOC(nextSize);
- if (tmpPointer == NULL) {
- return -1;
- }
- if (memcpy_s(tmpPointer, nextSize, floatSpec->floatStr, oriBufSize) != EOK) {
- SECUREC_FREE(tmpPointer); /* This is a dead code, just to meet the coding requirements */
- return -1;
- }
- if (memset_s(floatSpec->floatStr, oriBufSize, 0, oriBufSize) != EOK) {
- SECUREC_FREE(tmpPointer); /* This is a dead code, just to meet the coding requirements */
- return -1;
- }
- SECUREC_FREE(floatSpec->floatStr);
-
- floatSpec->floatStr = (SecChar *) (tmpPointer);
- floatSpec->allocatedFloatStr = (SecChar *) (tmpPointer); /* use to clear free on stack warning */
- floatSpec->floatStrSize *= SECUREC_BUF_EXT_MUL; /* this is OK, oriBufSize plus 1 just clear warning */
- return 0;
- }
- }
- return -1;
- }
- #endif
-
- #ifndef SECUREC_FOR_WCHAR
- /* LSD only multi-bytes string need isleadbyte() function */
- static 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
- */
- static void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec)
- {
- #if defined(SECUREC_FOR_WCHAR) && (defined(SECUREC_COMPATIBLE_WIN_FORMAT))
- signed char flagForUpperType = -1;
- signed char flagForLowerType = 1;
- #else
- signed char flagForUpperType = 1;
- signed char flagForLowerType = -1;
- #endif
- /* if no l or h flag */
- if (spec->isWChar == 0) {
- if ((ch == SECUREC_CHAR('C')) || (ch == SECUREC_CHAR('S'))) {
- spec->isWChar = flagForUpperType;
- } else {
- spec->isWChar = flagForLowerType;
- }
- }
- return;
- }
- /*
- * decode %l %ll
- */
- static 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->isWChar = 1;
- }
- *format = fmt;
- }
-
- /*
- * decode %I %I43 %I64 %Id %Ii %Io ...
- * set finishFlag to 1 finish Flag
- */
- static 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;
- }
- }
-
- static int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec)
- {
- const SecUnsignedChar *fmt = *format;
- while (SECUREC_IS_DIGIT(*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
- */
- static void SecSetDefaultScanSpec(SecScanSpec *spec)
- {
- 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->comChr = 0;
- spec->isWChar = 0;
- spec->suppress = 0;
- }
-
- /*
- * decode qualifier %I %L %h ...
- * set finishFlag to 1 finish Flag
- */
- static 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; /* h for SHORT , hh for CHAR */
- spec->isWChar = -1;
- break;
- #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
- case SECUREC_CHAR('j'):
- spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; /* intmax_t or uintmax_t */
- spec->isInt64Arg = 1;
- break;
- case SECUREC_CHAR('t'): /* 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'): /* 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->isWChar = 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
- */
- static 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
- */
- static int SecDecodeClearFormat(const SecUnsignedChar *format, int *comChr)
- {
- 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 */
- }
- }
- *comChr = ch;
- return 0;
- }
-
- /*
- * add L'\0' for wchar string , add '\0' for char string
- */
- static void SecAddEndingZero(void *ptr, const SecScanSpec *spec)
- {
- *(char *)ptr = '\0';
- (void)spec; /* clear not use */
- #if SECUREC_HAVE_WCHART
- if (spec->isWChar > 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 comChr = 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, &comChr) != 0) {
- return;
- }
-
- if ((buffer != NULL) && (*buffer != SECUREC_CHAR('\0')) && (comChr != 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
- */
- static 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
- */
- static int SecIsLongBitEqual(int bitNum)
- {
- return (unsigned int)bitNum == SECUREC_LONG_BIT_NUM;
- }
- #endif
- /*
- * Convert hexadecimal characters to decimal value
- */
- static 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(SecInt ch, 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;
- }
- #else
- if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
- decimalEdge = SECUREC_MAX_32BITS_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)ch - SECUREC_CHAR('0'))) {
- spec->beyondMax = 1;
- }
- }
- #endif
- spec->number += (unsigned long)((SecUnsignedInt)ch - SECUREC_CHAR('0'));
-
- }
-
-
- /*
- * Parse Hex character to integer for 32bit .
- */
- static void SecDecodeNumberHex(SecInt ch, 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(ch);
- }
-
-
- /*
- * Parse Octal character to integer for 32bit .
- */
- static void SecDecodeNumberOctal(SecInt ch, 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)ch - SECUREC_CHAR('0'));
- }
-
-
- #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
- /* Compatible with integer negative values other than int */
- static void SecFinishNumberNegativeOther(int comChr, int numberWidth, SecScanSpec *spec)
- {
- if ((comChr == SECUREC_CHAR('d')) || (comChr == SECUREC_CHAR('i'))) {
- if (spec->number > (unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1))) {
- spec->number = (unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1));
- } else {
- spec->number = (unsigned long)(-(long)spec->number);
- }
- if (spec->beyondMax != 0) {
- if (numberWidth < SECUREC_NUM_WIDTH_INT) {
- spec->number = 0;
- } else if (numberWidth == SECUREC_NUM_WIDTH_LONG) {
- spec->number = ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1)));
- }
- }
- } else { /* 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 */
- static void SecFinishNumberNegativeInt(int comChr, SecScanSpec *spec)
- {
- if ((comChr == SECUREC_CHAR('d')) || (comChr == 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 { /* 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 */
- static void SecFinishNumberPositiveOther(int comChr, int numberWidth, SecScanSpec *spec)
- {
- if (comChr == SECUREC_CHAR('d') || comChr == SECUREC_CHAR('i')) {
- if (spec->number > ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1)) - 1)) {
- spec->number = ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1)) - 1);
- }
- if ((spec->beyondMax != 0 && numberWidth < SECUREC_NUM_WIDTH_INT)) {
- spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
- }
- if (spec->beyondMax != 0 && numberWidth == SECUREC_NUM_WIDTH_LONG) {
- spec->number = ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1)) - 1);
- }
- } else {
- if (spec->beyondMax != 0) {
- spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
- }
- }
- }
-
- /* Compatible processing of integer positive numbers */
- static void SecFinishNumberPositiveInt(int comChr, SecScanSpec *spec)
- {
- if ((comChr == SECUREC_CHAR('d')) || (comChr == 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 { /* 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(SecInt ch, 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)ch - SECUREC_CHAR('0'))) {
- spec->beyondMax = 1;
- }
- }
- #endif
- spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)ch - SECUREC_CHAR('0'));
- }
-
- /*
- * Parse Hex character to integer for 64bit .
- */
- static void SecDecodeNumber64Hex(SecInt ch, 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(ch);
-
- }
-
- /*
- * Parse Octal character to integer for 64bit .
- */
- static void SecDecodeNumber64Octal(SecInt ch, 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)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])(SecInt ch, SecScanSpec *spec) = \
- { SecDecodeNumberHex, SecDecodeNumber64Hex };
- static void (*g_secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecInt ch, SecScanSpec *spec) = \
- { SecDecodeNumberOctal, SecDecodeNumber64Octal };
- static void (*g_secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecInt ch, SecScanSpec *spec) = \
- { SecDecodeNumberDecimal, SecDecodeNumber64Decimal };
-
- /*
- * Parse 64-bit integer formatted input, return 0 when ch is a number.
- */
- static int SecDecodeNumber(SecInt ch, SecScanSpec *spec)
- {
- if (spec->comChr == SECUREC_CHAR('x') || spec->comChr == SECUREC_CHAR('p')) {
- if (SECUREC_IS_XDIGIT(ch)) {
- (*g_secDecodeNumberHex[spec->isInt64Arg])(ch, spec);
- } else {
- return -1;
- }
- return 0;
- }
- if (!(SECUREC_IS_DIGIT(ch))) {
- return -1;
- }
- if (spec->comChr == SECUREC_CHAR('o')) {
- if (ch < SECUREC_CHAR('8')) {
- (*g_secDecodeNumberOctal[spec->isInt64Arg])(ch, spec);
- } else {
- return -1;
- }
- } else { /* comChr is 'd' */
- (*g_secDecodeNumberDecimal[spec->isInt64Arg])(ch, 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->oriComChr, spec);
- } else {
- SecFinishNumberNegativeOther(spec->oriComChr, spec->numberWidth, spec);
- }
- } else {
- if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
- SecFinishNumberPositiveInt(spec->oriComChr, spec);
- } else {
- SecFinishNumberPositiveOther(spec->oriComChr, spec->numberWidth, spec);
- }
- }
- #else
- if (spec->negative != 0) {
- #if defined(__hpux)
- if (spec->oriComChr != 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->oriComChr == (SECUREC_CHAR('d')) || (spec->oriComChr == 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 { /* o, u, x, X, p */
- spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
- if (spec->beyondMax != 0) {
- spec->number64 = SECUREC_MAX_64BITS_VALUE;
- }
- }
- } else {
- if ((spec->oriComChr == SECUREC_CHAR('d')) || (spec->oriComChr == 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->oriComChr != 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
- */
- static 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 ret = fread(stream->base, (size_t)((unsigned int)stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE),
- (size_t)1, stream->pf);
- if ((ret == 1 || ret == 0) && (ftell(stream->pf) < stream->oriFilePos + stream->fileRealRead)) {
- (void)fseek(stream->pf, stream->oriFilePos + stream->fileRealRead, SEEK_SET);
- }
- }
-
- #else
- /* in 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
- */
- static 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
-
- static void SecSkipSpaceFormat(const SecUnsignedChar **format)
- {
- const SecUnsignedChar *fmt = *format;
- while (SECUREC_IS_SPACE(*fmt)) {
- ++fmt;
- }
- *format = fmt;
- }
- #ifndef SECUREC_FOR_WCHAR
- /*
- * Handling multi-character characters
- */
- static int SecDecodeLeadByte(SecInt ch, const SecUnsignedChar **format, SecFileStream *stream, int *counter)
- {
- #if SECUREC_HAVE_MBTOWC
- char temp[SECUREC_MULTI_BYTE_MAX_LEN];
- const SecUnsignedChar *fmt = *format;
- wchar_t tempWChar = L'\0';
- int ch2 = SecGetChar(stream, counter);
- if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != (ch2)) {
- /* LSD in console mode, ungetc twice may cause problem */
- SecUnGetChar(ch2, stream, counter);
- SecUnGetChar(ch, stream, counter);
- return -1;
- }
- ++fmt;
- if (MB_CUR_MAX >= SECUREC_UTF8_BOM_HEADER_SIZE &&
- (((unsigned char)ch & 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 */
- int ch3 = SecGetChar(stream, counter);
- temp[0] = (char)ch;
- 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) != (int)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(ch, stream, counter);
- (void)format;
- return -1;
- #endif
- }
- #endif
-
-
-
- /*
- * Resolving sequence of characters from %[ format
- */
- static int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable)
- {
- const SecUnsignedChar *fmt = *format;
- SecUnsignedChar prevChar = 0;
- SecUnsignedChar expCh;
- 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;
- SECUREC_BRACKET_SET_BIT(bracketTable->table, SECUREC_CHAR(']'));
- }
- while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
- expCh = *fmt++;
- if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) {
- /* normal character */
- prevChar = expCh;
- SECUREC_BRACKET_SET_BIT(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))
- /* %[z-a] */
- last = prevChar;
-
- #else
- SECUREC_BRACKET_SET_BIT(bracketTable->table, SECUREC_CHAR('-'));
- SECUREC_BRACKET_SET_BIT(bracketTable->table, expCh);
- continue;
- #endif
- }
- /* format %[a-\xff] last is 0xFF, condition (rnch <= last) cause dead loop */
- for (expCh = prevChar; expCh < last; ++expCh) {
- SECUREC_BRACKET_SET_BIT(bracketTable->table, expCh);
- }
- SECUREC_BRACKET_SET_BIT(bracketTable->table, last);
- prevChar = 0;
- }
- }
- *format = fmt;
- return 0;
- }
-
-
- #ifdef SECUREC_FOR_WCHAR
- static int SecInputForWchar(SecInt ch, SecScanSpec *spec)
- {
- void *endPtr = spec->argPtr;
- if (spec->isWChar > 0) {
- *(wchar_t UNALIGNED *)endPtr = (wchar_t)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)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
- static int SecInputForChar(SecInt ch, SecScanSpec *spec, SecFileStream *stream, int *charCount)
- {
- void *endPtr = spec->argPtr;
- if (spec->isWChar > 0) {
- wchar_t tempWChar = L'?'; /* set default char as ? */
- #if SECUREC_HAVE_MBTOWC
- char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1];
- temp[0] = (char)ch;
- temp[1] = '\0';
- #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
- if (SecIsLeadByte(ch)) {
- temp[1] = (char)SecGetChar(stream, charCount);
- 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(ch)) {
- int convRes = 0;
- int di = 1;
- /* in Linux like system, the string is encoded in UTF-8 */
- while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) {
- temp[di++] = (char)SecGetChar(stream, charCount);
- temp[di] = '\0';
- convRes = mbtowc(&tempWChar, temp, sizeof(temp));
- }
- if (convRes <= 0) {
- tempWChar = L'?';
- }
- } else {
- if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) {
- /* no string termination error for tool */
- tempWChar = L'?';
- }
- }
- #endif
- #endif /* SECUREC_HAVE_MBTOWC */
- *(wchar_t UNALIGNED *)endPtr = tempWChar;
- /* just copy L'?' if mbtowc fails, errno is set by mbtowc */
- endPtr = (wchar_t *)endPtr + 1;
- --spec->arrayWidth;
- (void)charCount;
- (void)stream;
- } else {
- *(char *)endPtr = (char)ch;
- endPtr = (char *)endPtr + 1;
- --spec->arrayWidth;
- }
- spec->argPtr = endPtr;
- return 0;
- }
- #endif
-
-
- #if SECUREC_ENABLE_SCANF_FLOAT
-
- /* no not use localeconv()->decimal_pointif onlay support '.' */
- #define SECURE_IS_FLOAT_DECIMAL(ch) ((ch) == SECUREC_CHAR('.'))
- /*
- * init SecFloatSpec befor parse format
- */
- static void SecInitFloatSpec(SecFloatSpec *floatSpec)
- {
- floatSpec->floatStr = floatSpec->buffer;
- floatSpec->allocatedFloatStr = NULL;
- floatSpec->floatStrSize = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]);
- floatSpec->floatStr = floatSpec->buffer;
- floatSpec->floatStrUsedLen = 0;
- }
-
- static void SecClearFloatSpec(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 is a dead code, just to meet the coding requirements */
- }
- if (floatSpec->allocatedFloatStr != NULL) {
- /* pFloatStr can be alloced in SecUpdateFloatString function, clear and free it */
- if (memset_s(floatSpec->allocatedFloatStr, floatSpec->floatStrSize * sizeof(SecChar), 0,
- floatSpec->floatStrSize * sizeof(SecChar)) != EOK) {
- *doneCount = 0; /* This is a dead code, just to meet the coding requirements */
- }
- SECUREC_FREE(floatSpec->allocatedFloatStr);
- floatSpec->allocatedFloatStr = NULL;
- floatSpec->floatStr = NULL;
- }
- }
-
-
- /*
- * scan value of exponent.
- * return 0 OK
- */
- static int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec, int *charCount)
- {
- SecInt ch = SecGetChar(stream, charCount);
- if (ch == SECUREC_CHAR('+') || ch == SECUREC_CHAR('-')) {
- if (ch == SECUREC_CHAR('-') && SecUpdateFloatString((SecChar)'-', floatSpec) != 0) {
- return -1;
- }
- if (spec->width != 0) {
- ch = SecGetChar(stream, charCount);
- --spec->width;
- }
- }
-
- while (SECUREC_IS_DIGIT(ch) && spec->width-- != 0) {
- if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) {
- return -1;
- }
- ch = SecGetChar(stream, charCount);
- }
- return 0;
- }
-
- /*
- * scan %f.
- * return 0 OK
- */
- static int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec, int *charCount)
- {
- int started = -1;
- SecInt ch = SecGetChar(stream, charCount);
-
- floatSpec->floatStrUsedLen = 0;
- if (ch == SECUREC_CHAR('-')) {
- floatSpec->floatStr[floatSpec->floatStrUsedLen++] = SECUREC_CHAR('-');
- --spec->width;
- ch = SecGetChar(stream, charCount);
- } else if (ch == SECUREC_CHAR('+')) {
- --spec->width;
- ch = SecGetChar(stream, charCount);
- }
-
- if (spec->widthSet == 0) { /* must care width */
- spec->width = -1; /* -1 is unlimited */
- }
-
- /* now get integral part */
- while (SECUREC_IS_DIGIT(ch) && spec->width-- != 0) {
- started = 0;
- /* ch must be '0' - '9' */
- if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) {
- return -1;
- }
- ch = SecGetChar(stream, charCount);
- }
-
- /* now get fractional part */
- if (SECURE_IS_FLOAT_DECIMAL((SecChar)ch) && spec->width-- != 0) {
- /* now check for decimal */
- if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) {
- return -1;
- }
- ch = SecGetChar(stream, charCount);
- while (SECUREC_IS_DIGIT(ch) && spec->width-- != 0) {
- started = 0;
- if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) {
- return -1;
- }
- ch = SecGetChar(stream, charCount);
- }
- }
-
- /* now get exponent part */
- if (started == 0 && (ch == SECUREC_CHAR('e') || ch == SECUREC_CHAR('E')) && spec->width-- != 0) {
- if (SecUpdateFloatString((SecChar)'e', floatSpec) != 0) {
- return -1;
- }
- if (SecInputFloatE(stream, spec, floatSpec, charCount) != 0) {
- return -1;
- }
- }
- /* un set the last character that is not a floating point number */
- SecUnGetChar(ch, stream, charCount);
- /* Make sure have a string terminator, buffer is large enough */
- floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0');
- return started;
-
- }
- #endif
-
- /*
- * scan digital part of %d %i %o %u %x %p.
- * return 0 OK
- */
- static int SecInputNumberDigital(SecInt firstCh, SecFileStream *stream, SecScanSpec *spec, int *charCount)
- {
- SecInt ch = firstCh;
- int loopFlag = 0;
- int started = -1;
- while (loopFlag == 0) {
- /* decode ch to number */
- loopFlag = SecDecodeNumber(ch, spec);
- if (loopFlag == 0) {
- started = 0;
- if (spec->widthSet != 0 && --spec->width == 0) {
- loopFlag = 1;
- } else {
- ch = SecGetChar(stream, charCount);
- }
- } else {
- SecUnGetChar(ch, stream, 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
- */
- static int SecInputNumber(SecFileStream *stream, SecScanSpec *spec, int *charCount)
- {
- SecInt ch = SecGetChar(stream, charCount);
-
- if (ch == SECUREC_CHAR('+') || ch == SECUREC_CHAR('-')) {
- if (ch == SECUREC_CHAR('-')) {
- spec->negative = 1;
- }
- if (spec->widthSet != 0 && --spec->width == 0) {
- return -1;
- } else {
- ch = SecGetChar(stream, charCount);
- }
- }
-
- if (spec->oriComChr == SECUREC_CHAR('i')) {
- /* i could be d, o, or x, use d as default */
- spec->comChr = SECUREC_CHAR('d');
- }
-
- if (spec->oriComChr == SECUREC_CHAR('x') || spec->oriComChr == SECUREC_CHAR('i')) {
- if (ch != SECUREC_CHAR('0')) {
- /* scan number */
- return SecInputNumberDigital(ch, stream, spec, charCount);
- }
- /* now input string may be 0x123 or 0X123 or just 0 */
- /* get next char */
- ch = SecGetChar(stream, charCount);
- if ((SecChar)(ch) == SECUREC_CHAR('x') || (SecChar)ch == SECUREC_CHAR('X')) {
- spec->comChr = SECUREC_CHAR('x');
- ch = SecGetChar(stream, 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->oriComChr != SECUREC_CHAR('x')) {
- spec->comChr = SECUREC_CHAR('o');
- }
- /* unset the character after 0 back to stream, input only '0' result is OK */
- SecUnGetChar(ch, stream, charCount);
- ch = SECUREC_CHAR('0');
- }
- }
- /* scan number */
- return SecInputNumberDigital(ch, stream, spec, charCount);
- }
- /*
- * scan %c %s %[
- * return 0 OK
- */
- static int SecInputString(SecFileStream *stream, SecScanSpec *spec,
- const SecBracketTable *bracketTable, int *charCount, int *doneCount)
- {
- void *startPtr = spec->argPtr;
- int suppressed= 0;
- int errNoMem = 0;
-
- while (spec->widthSet == 0 || spec->width-- != 0) {
- SecInt ch = SecGetChar(stream, charCount);
- /* char condition or string condition and bracket condition.
- * only supports wide characters with a maximum length of two bytes
- */
- if ((ch != SECUREC_EOF) && (spec->comChr == SECUREC_CHAR('c') ||
- SECUREC_SCANF_STRING_CONDITION(spec->comChr, ch) ||
- SECUREC_SCANF_BRACKET_CONDITION(spec->comChr, ch, bracketTable->table, bracketTable->mask))) {
- if (spec->suppress != 0) {
- /* Used to identify processed data for %*
- * use endPtr 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(ch, spec);
- #else
- errNoMem = SecInputForChar(ch, spec, stream, charCount);
- #endif
- if (errNoMem != 0) {
- break;
- }
- } else {
- SecUnGetChar(ch, stream, charCount);
- break;
- }
- }
-
- if (errNoMem != 0) {
- /* In case of error, blank out the input buffer */
- if (spec->suppress == 0) {
- 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->suppress == 0) {
- if (spec->comChr != 'c') {
- /* null-terminate strings */
- SecAddEndingZero(spec->argPtr, spec);
- }
- *doneCount = *doneCount + 1;
- }
- return 0;
- }
-
- #ifdef SECUREC_FOR_WCHAR
- /*
- * alloce buffer for wchar version of %[.
- * return 0 OK
- */
- static 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 %[
- */
- static 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 vsscanf_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 vswscanf_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;
- SecInt ch = 0;
- int charCount = 0;
- int doneCount = 0;
- int formatError = 0;
- int paraIsNull = 0;
- #if SECUREC_ENABLE_SCANF_FLOAT
- SecFloatSpec floatSpec;
- #endif
- int match = 0;
- int errRet = 0;
- #if SECUREC_ENABLE_SCANF_FLOAT
- SecInitFloatSpec(&floatSpec);
- #endif
- /* 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 (SECUREC_IS_SPACE(*format)) {
- SecInt nonSpaceChar = SecSkipSpaceChar(stream, &charCount);
- /* eat all space chars and put fist no space char backup */
- SecUnGetChar(nonSpaceChar, stream, &charCount);
- SecSkipSpaceFormat(&format);
- continue;
- }
-
- if (*format != SECUREC_CHAR('%')) {
- ch = SecGetChar(stream, &charCount);
- if ((int)(*format++) != (int)(ch)) {
- SecUnGetChar(ch, stream, &charCount);
- ++errRet; /* use plus to clear 845 */
- continue;
- }
- #ifndef SECUREC_FOR_WCHAR
- if (SecIsLeadByte(ch) && SecDecodeLeadByte(ch, &format, stream, &charCount) != 0) {
- ++errRet;
- continue;
- }
- #endif
- /* for next %n */
- if ((ch == SECUREC_EOF) && ((*format != SECUREC_CHAR('%')) || (*(format + 1) != SECUREC_CHAR('n')))) {
- 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 SECUREC_HAVE_WCHART == 0
- /* in kernel not support wide char */
- if (spec.isWChar > 0) {
- formatError = 1;
- ++errRet;
- continue;
- }
- #endif
- if (spec.widthSet != 0 && spec.width == 0) {
- /* 0 width in format */
- ++errRet;
- continue;
- }
-
- spec.comChr = (unsigned char)(*format) | (SECUREC_CHAR('a') - SECUREC_CHAR('A')); /* to lowercase */
- spec.oriComChr = spec.comChr;
-
- if (spec.comChr != SECUREC_CHAR('n')) {
- if (spec.comChr != SECUREC_CHAR('c') && spec.comChr != SECUREC_BRACE) {
- ch = SecSkipSpaceChar(stream, &charCount);
- } else {
- ch = SecGetChar(stream, &charCount);
- }
- if (ch == SECUREC_EOF) {
- ++errRet;
- continue;
- }
- }
-
- /* now no 0 width in format and get one char from input */
- switch (spec.comChr) {
- 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 (spec.arrayWidth == 0 || (spec.isWChar <= 0 && spec.arrayWidth > SECUREC_STRING_MAX_LEN) ||
- (spec.isWChar > 0 && spec.arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN)) {
- /* do not clear buffer just go error */
- ++errRet;
- continue;
- }
- /* One element is needed for '\0' for %s and %[ */
- if (spec.comChr != 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.comChr == 'c') {
- if (spec.widthSet == 0) {
- spec.widthSet = 1;
- spec.width = 1;
- }
- } else if (spec.comChr == 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')) {
- if (spec.suppress == 0 && spec.arrayWidth > 0) {
- SecAddEndingZero(spec.argPtr, &spec);
- }
- ++errRet;
- /* truncated format */
- continue;
- }
-
- }
- /* un set last char to stream */
- SecUnGetChar(ch, stream, &charCount);
- /* scanset completed. Now read string */
- if (SecInputString(stream, &spec, &bracketTable, &charCount, &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'):
- /* un set last char to stream */
- SecUnGetChar(ch, stream, &charCount);
- if (SecInputNumber(stream, &spec, &charCount) != 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)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
- /* un set last char to stream */
- SecUnGetChar(ch, stream, &charCount);
- if (SecInputFloat(stream, &spec, &floatSpec, &charCount) != 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)ch) {
- SecUnGetChar(ch, stream, &charCount);
- formatError = 1;
- ++errRet;
- continue;
- } else {
- --match;
- }
- }
-
- ++match;
- ++format;
- if ((ch == SECUREC_EOF) && ((*format != SECUREC_CHAR('%')) || (*(format + 1) != SECUREC_CHAR('n')))) {
- break;
- }
- }
-
- #ifdef SECUREC_FOR_WCHAR
- SecFreeBracketTable(&bracketTable);
- #endif
-
- #if SECUREC_ENABLE_SCANF_FLOAT
- SecClearFloatSpec(&floatSpec, &doneCount);
- #endif
-
- #if SECUREC_ENABLE_SCANF_FILE
- SecAdjustStream(stream);
- #endif
-
- if (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 stdin or buffer
- */
- static SecInt SecGetCharFromStdin(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 stdin or buffer use std function
- */
- static SecInt SecGetCharFromStdin(const SecFileStream *stream)
- {
- SecInt ch;
- ch = SECUREC_GETC(stream->pf);
- return ch;
- }
- #endif
-
- static void SecSkipBomHeader(SecFileStream *stream)
- {
- #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))) {
-
- /* the stream->count must be a multiple of sizeof(SecChar),
- * otherwise this function will return SECUREC_EOF when read the last character
- */
- if ((stream->count - SECUREC_BOM_HEADER_SIZE) % (int)sizeof(SecChar) != 0) {
- int ret = (int)fread(stream->base + stream->count, (size_t)1,
- (size_t)SECUREC_BOM_HEADER_SIZE, stream->pf);
- if (ret > 0 && ret <= SECUREC_BUFFERED_BLOK_SIZE) {
- stream->count += ret;
- }
- }
- /* it's BOM header, skip */
- stream->count -= SECUREC_BOM_HEADER_SIZE;
- stream->cur += SECUREC_BOM_HEADER_SIZE;
- }
- #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, skip */
- stream->count -= SECUREC_UTF8_BOM_HEADER_SIZE;
- stream->cur += SECUREC_UTF8_BOM_HEADER_SIZE;
- }
- #endif
- }
- /*
- * Get char from file stream or buffer
- */
- static SecInt SecGetCharFromFile(SecFileStream *stream)
- {
- SecInt ch;
- if (stream->count == 0) {
- int firstReadOnFile = 0;
- /* load file to buffer */
- if (stream->base == NULL) {
- stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE + 1);
- if (stream->base == NULL) {
- return SECUREC_EOF;
- }
- stream->base[SECUREC_BUFFERED_BLOK_SIZE] = '\0'; /* for tool Warning string null */
- }
- /* LSD add 2014.3.21 */
- if (stream->oriFilePos == SECUREC_UNINITIALIZED_FILE_POS) {
- stream->oriFilePos = ftell(stream->pf); /* save original file read position */
- firstReadOnFile = 1;
- }
- stream->count = (int)fread(stream->base, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf);
- stream->base[SECUREC_BUFFERED_BLOK_SIZE] = '\0'; /* for tool Warning string null */
- if (stream->count == 0 || stream->count > SECUREC_BUFFERED_BLOK_SIZE) {
- return SECUREC_EOF;
- }
- stream->cur = stream->base;
- stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG;
- if (firstReadOnFile != 0) {
- SecSkipBomHeader(stream);
- }
- }
- /* according wchar_t has two bytes */
- ch = (SecInt)((stream->count -= (int)sizeof(SecChar)) >= 0 ? \
- (SecInt)(SECUREC_CHAR_MASK & \
- (unsigned int)(int)(*((const SecChar *)(const void *)stream->cur))) : SECUREC_EOF);
- stream->cur += sizeof(SecChar);
-
- if (ch != SECUREC_EOF && stream->base != NULL) {
- stream->fileRealRead += (int)sizeof(SecChar);
- }
- return ch;
- }
- #endif
-
- /*
- * Get char for wchar version
- */
- static SecInt SecGetChar(SecFileStream *stream, int *counter)
- {
- SecInt ch = SECUREC_EOF;
- #if SECUREC_ENABLE_SCANF_FILE
- if ((stream->flag & SECUREC_FROM_STDIN_FLAG) > 0) {
- ch = SecGetCharFromStdin(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 */
- ch = (SecInt)((stream->count -= (int)sizeof(SecChar)) >= 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
- */
- static void SecUnGetCharImpl(SecInt ch, SecFileStream *stream)
- {
- if ((stream->flag & SECUREC_FROM_STDIN_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
- */
- static void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter)
- {
- if (ch != SECUREC_EOF) {
- SecUnGetCharImpl(ch, stream);
- }
- *counter = *counter - 1;
- }
-
- /*
- * Skip space char by isspace
- */
- static SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter)
- {
- SecInt ch;
- do {
- ch = SecGetChar(stream, counter);
- } while (ch != SECUREC_EOF && SECUREC_IS_SPACE(ch));
- return ch;
- }
- #endif /* __INPUT_INL__5D13A042_DC3F_4ED9_A8D1_882811274C27 */
|