123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229 |
- /*
- * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved.
- * Licensed under Mulan PSL v2.
- * You can use this software according to the terms and conditions of the Mulan PSL v2.
- * You may obtain a copy of Mulan PSL v2 at:
- * http://license.coscl.org.cn/MulanPSL2
- * 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 v2 for more details.
- * Description: Used by secureinput_a.c and secureinput_w.c to include.
- * This file provides a template function for ANSI and UNICODE compiling by
- * different type definition. The functions of SecInputS or
- * SecInputSW provides internal implementation for scanf family API, such as sscanf_s, fscanf_s.
- * Create: 2014-02-25
- * Notes: The formatted input processing results of integers on different platforms are different.
- */
- /*
- * [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
- #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
- #ifndef EOF
- #define EOF (-1)
- #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 1024U
- #if defined(SECUREC_VXWORKS_PLATFORM) && !defined(va_copy) && !defined(__va_copy)
- /* The name is the same as system macro. */
- #define __va_copy(dest, src) do { \
- size_t destSize_ = (size_t)sizeof(dest); \
- size_t srcSize_ = (size_t)sizeof(src); \
- if (destSize_ != srcSize_) { \
- SECUREC_MEMCPY_WARP_OPT((dest), (src), sizeof(va_list)); \
- } else { \
- SECUREC_MEMCPY_WARP_OPT(&(dest), &(src), 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 2147483648UL
- #define SECUREC_MAX_32BITS_POS_VALUE 2147483647UL
- #define SECUREC_MAX_32BITS_VALUE 4294967295UL
- #define SECUREC_MAX_32BITS_VALUE_INC 4294967296UL
- #define SECUREC_MAX_32BITS_VALUE_DIV_TEN 429496729UL
- #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
- #define SECUREC_CONVERT_IS_SIGNED(conv) ((conv) == 'd' || (conv) == 'i')
- #endif
- #define SECUREC_BRACE '{' /* [ to { */
- #define SECUREC_FILED_WIDTH_ENOUGH(spec) ((spec)->widthSet == 0 || (spec)->width > 0)
- #define SECUREC_FILED_WIDTH_DEC(spec) do { \
- if ((spec)->widthSet != 0) { \
- --(spec)->width; \
- } \
- } SECUREC_WHILE_ZERO
- #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).arrayWidth > SECUREC_STRING_MAX_LEN)
- #endif
- #ifdef SECUREC_ON_64BITS
- /* Use 0xffffffffUL mask to pass integer as array length */
- #define SECUREC_GET_ARRAYWIDTH(argList) (((size_t)va_arg((argList), size_t)) & 0xffffffffUL)
- #else /* !SECUREC_ON_64BITS */
- #define SECUREC_GET_ARRAYWIDTH(argList) ((size_t)va_arg((argList), size_t))
- #endif
- 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 *floatStr; /* Initialization must point to buffer */
- SecChar *allocatedFloatStr; /* Initialization must be NULL to store alloced point */
- SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1];
- } SecFloatSpec;
- #endif
- #define SECUREC_NUMBER_STATE_DEFAULT 0U
- #define SECUREC_NUMBER_STATE_STARTED 1U
- typedef struct {
- SecInt ch; /* Char read from input */
- int charCount; /* Number of characters processed */
- void *argPtr; /* Variable parameter pointer, point to the end of the string */
- size_t arrayWidth; /* Length of pointer Variable parameter, in charaters */
- SecUnsignedInt64 number64; /* Store input number64 value */
- unsigned long number; /* Store input number32 value */
- int numberWidth; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */
- int numberArgType; /* 1 for 64-bit integer, 0 otherwise. use it as decode function index */
- unsigned int negative; /* 0 is positive */
- #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
- unsigned int beyondMax; /* Non-zero means beyond */
- #endif
- unsigned int numberState; /* Identifies whether to start processing numbers, 1 is can input number */
- 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 */
- unsigned char suppress; /* 0 is not have %* in format */
- } SecScanSpec;
- #ifdef SECUREC_FOR_WCHAR
- #define SECUREC_GETC fgetwc
- #define SECUREC_UN_GETC ungetwc
- /* Only supports wide characters with a maximum length of two bytes in format string */
- #define SECUREC_BRACKET_CHAR_MASK 0xffffU
- #else
- #define SECUREC_GETC fgetc
- #define SECUREC_UN_GETC ungetc
- #define SECUREC_BRACKET_CHAR_MASK 0xffU
- #endif
- #define SECUREC_CHAR_SIZE ((unsigned int)(sizeof(SecChar)))
- /* To avoid 648, mask high bit: 0x00ffffff 0x0000ffff or 0x00000000 */
- #define SECUREC_CHAR_MASK_HIGH (((((((((unsigned int)(-1) >> SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
- SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
- SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE) >> \
- SECUREC_CHAR_SIZE) >> SECUREC_CHAR_SIZE)
- /* For char is 0xff, wcahr_t is 0xffff or 0xffffffff. */
- #define SECUREC_CHAR_MASK (~((((((((((unsigned int)(-1) & SECUREC_CHAR_MASK_HIGH) << \
- SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
- SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
- SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE) << \
- SECUREC_CHAR_SIZE) << SECUREC_CHAR_SIZE))
- /* According wchar_t has multiple bytes, so use sizeof */
- #define SECUREC_GET_CHAR(stream, outCh) do { \
- if ((stream)->count >= sizeof(SecChar)) { \
- *(outCh) = (SecInt)(SECUREC_CHAR_MASK & \
- (unsigned int)(int)(*((const SecChar *)(const void *)(stream)->cur))); \
- (stream)->cur += sizeof(SecChar); \
- (stream)->count -= sizeof(SecChar); \
- } else { \
- *(outCh) = SECUREC_EOF; \
- } \
- } SECUREC_WHILE_ZERO
- #define SECUREC_UN_GET_CHAR(stream) do { \
- if ((stream)->cur > (stream)->base) { \
- (stream)->cur -= sizeof(SecChar); \
- (stream)->count += sizeof(SecChar); \
- } \
- } SECUREC_WHILE_ZERO
- /* Convert wchar_t to int and then to unsigned int to keep data clearing warning */
- #define SECUREC_TO_LOWERCASE(chr) ((int)((unsigned int)(int)(chr) | (unsigned int)('a' - 'A')))
- /* Record a flag for each bit */
- #define SECUREC_BRACKET_INDEX(x) ((unsigned int)(x) >> 3U)
- #define SECUREC_BRACKET_VALUE(x) ((unsigned char)(1U << ((unsigned int)(x) & 7U)))
- #if SECUREC_IN_KERNEL
- #define SECUREC_CONVERT_IS_UNSIGNED(conv) ((conv) == 'x' || (conv) == 'o' || (conv) == 'u')
- #endif
- /*
- * 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_BRACKET_CHAR_MASK));
- unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
- /* Do not use |= optimize this code, it will cause compiling warning */
- table[tableIndex] = (unsigned char)(table[tableIndex] | tableValue);
- }
- SECUREC_INLINE void SecBracketSetBitRange(unsigned char *table, SecUnsignedChar startCh, SecUnsignedChar endCh)
- {
- SecUnsignedChar expCh;
- /* %[a-z] %[a-a] Format %[a-\xff] end is 0xFF, condition (expCh <= endChar) cause dead loop */
- for (expCh = startCh; expCh < endCh; ++expCh) {
- SecBracketSetBit(table, expCh);
- }
- SecBracketSetBit(table, endCh);
- }
- /*
- * 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_BRACKET_CHAR_MASK));
- unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)ch & SECUREC_BRACKET_CHAR_MASK));
- #ifdef SECUREC_FOR_WCHAR
- if (((unsigned int)(int)ch & (~(SECUREC_BRACKET_CHAR_MASK))) != 0) {
- /* The value of the wide character exceeds the size of two bytes */
- return 0;
- }
- return (int)(convChr == SECUREC_BRACE &&
- (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0);
- #else
- return (int)(convChr == SECUREC_BRACE &&
- (((unsigned int)bracketTable->table[tableIndex] ^ (unsigned int)bracketTable->mask) & tableValue) != 0);
- #endif
- }
- /*
- * String input ends when blank character is encountered
- */
- SECUREC_INLINE int SecCanInputString(int convChr, SecInt ch)
- {
- return (int)(convChr == '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 (int)(convChr == 'c');
- }
- /*
- * Determine if it is a 64-bit pointer function
- * Return 0 is not ,1 is 64bit pointer
- */
- SECUREC_INLINE int SecNumberArgType(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 int SecAssignNarrowFloat(const char *floatStr, const SecScanSpec *spec)
- {
- char *endPtr = NULL;
- double d;
- #if SECUREC_SUPPORT_STRTOLD
- if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG_LONG) {
- long double d2 = strtold(floatStr, &endPtr);
- if (endPtr == floatStr) {
- return -1;
- }
- *(long double UNALIGNED *)(spec->argPtr) = d2;
- return 0;
- }
- #endif
- d = strtod(floatStr, &endPtr);
- /* cannot detect if endPtr points to the end of floatStr,because strtod handles only two characters for 1.E */
- if (endPtr == floatStr) {
- return -1;
- }
- if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) {
- *(double UNALIGNED *)(spec->argPtr) = (double)d;
- } else {
- *(float UNALIGNED *)(spec->argPtr) = (float)d;
- }
- return 0;
- }
- #ifdef SECUREC_FOR_WCHAR
- /*
- * Convert a floating point wchar string to a floating point number
- * Success ret 0
- */
- SECUREC_INLINE int SecAssignWideFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
- {
- int retVal;
- /* Convert float string */
- size_t mbsLen;
- size_t tempFloatStrLen = (size_t)(floatSpec->floatStrUsedLen + 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) {
- SECUREC_FREE(tempFloatStr);
- return -1;
- }
- tempFloatStr[mbsLen] = '\0';
- retVal = SecAssignNarrowFloat(tempFloatStr, spec);
- SECUREC_FREE(tempFloatStr);
- return retVal;
- }
- #endif
- SECUREC_INLINE int SecAssignFloat(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
- {
- #ifdef SECUREC_FOR_WCHAR
- return SecAssignWideFloat(floatSpec, spec);
- #else
- return SecAssignNarrowFloat(floatSpec->floatStr, spec);
- #endif
- }
- /*
- * Init SecFloatSpec before 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->floatStrUsedLen = 0;
- }
- SECUREC_INLINE void SecFreeFloatSpec(SecFloatSpec *floatSpec, int *doneCount)
- {
- /* 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 SecExtendFloatLen 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 SecExtendFloatLen(SecFloatSpec *floatSpec)
- {
- 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 <= (size_t)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 (int)(ch == SECUREC_CHAR('.'));
- }
- SECUREC_INLINE int SecInputFloatSign(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
- {
- if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- return 0;
- }
- spec->ch = SecGetChar(stream, &(spec->charCount));
- if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
- SECUREC_FILED_WIDTH_DEC(spec); /* Make sure the count after un get char is correct */
- if (spec->ch == SECUREC_CHAR('-')) {
- floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('-');
- ++floatSpec->floatStrUsedLen;
- if (SecExtendFloatLen(floatSpec) != 0) {
- return -1;
- }
- }
- } else {
- SecUnGetChar(spec->ch, stream, &(spec->charCount));
- }
- return 0;
- }
- SECUREC_INLINE int SecInputFloatDigit(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
- {
- /* Now get integral part */
- while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- spec->ch = SecGetChar(stream, &(spec->charCount));
- if (SecIsDigit(spec->ch) == 0) {
- SecUnGetChar(spec->ch, stream, &(spec->charCount));
- return 0;
- }
- SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
- spec->numberState = SECUREC_NUMBER_STATE_STARTED;
- floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch;
- ++floatSpec->floatStrUsedLen;
- if (SecExtendFloatLen(floatSpec) != 0) {
- return -1;
- }
- }
- return 0;
- }
- /*
- * Scan value of exponent.
- * Return 0 OK
- */
- SECUREC_INLINE int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
- {
- if (SecInputFloatSign(stream, spec, floatSpec) == -1) {
- return -1;
- }
- if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
- return -1;
- }
- return 0;
- }
- SECUREC_INLINE int SecInputFloatFractional(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
- {
- if (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- spec->ch = SecGetChar(stream, &(spec->charCount));
- if (SecIsFloatDecimal((SecChar)spec->ch) == 0) {
- SecUnGetChar(spec->ch, stream, &(spec->charCount));
- return 0;
- }
- SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
- /* Now check for decimal */
- floatSpec->floatStr[floatSpec->floatStrUsedLen] = (SecChar)spec->ch;
- ++floatSpec->floatStrUsedLen;
- if (SecExtendFloatLen(floatSpec) != 0) {
- return -1;
- }
- if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
- return -1;
- }
- }
- return 0;
- }
- SECUREC_INLINE int SecInputFloatExponent(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
- {
- /* Now get exponent part */
- if (spec->numberState == SECUREC_NUMBER_STATE_STARTED && SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- spec->ch = SecGetChar(stream, &(spec->charCount));
- if (spec->ch != SECUREC_CHAR('e') && spec->ch != SECUREC_CHAR('E')) {
- SecUnGetChar(spec->ch, stream, &(spec->charCount));
- return 0;
- }
- SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
- floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('e');
- ++floatSpec->floatStrUsedLen;
- if (SecExtendFloatLen(floatSpec) != 0) {
- return -1;
- }
- if (SecInputFloatE(stream, spec, floatSpec) != 0) {
- return -1;
- }
- }
- return 0;
- }
- /*
- * Scan %f.
- * Return 0 OK
- */
- SECUREC_INLINE int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec)
- {
- floatSpec->floatStrUsedLen = 0;
- /* The following code sequence is strict */
- if (SecInputFloatSign(stream, spec, floatSpec) != 0) {
- return -1;
- }
- if (SecInputFloatDigit(stream, spec, floatSpec) != 0) {
- return -1;
- }
- if (SecInputFloatFractional(stream, spec, floatSpec) != 0) {
- return -1;
- }
- if (SecInputFloatExponent(stream, spec, floatSpec) != 0) {
- return -1;
- }
- /* Make sure have a string terminator, buffer is large enough */
- floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0');
- if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) {
- return 0;
- }
- return -1;
- }
- #endif
- #if (!defined(SECUREC_FOR_WCHAR) && SECUREC_HAVE_WCHART && SECUREC_HAVE_MBTOWC) || \
- (!defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION))
- /* 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 & 0x80U); /* Use bitwise operation to check if the most significant bit is 1 */
- #else
- return (int)isleadbyte((int)(c & 0xffU)); /* Use bitwise operations to limit character values to valid ranges */
- #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->numberArgType = 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->numberArgType = 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->numberArgType = 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->numberArgType = SecNumberArgType(sizeof(void *));
- } else {
- /* For %I */
- spec->numberArgType = SecNumberArgType(sizeof(void *));
- *finishFlag = 1;
- }
- }
- SECUREC_INLINE int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec)
- {
- const SecUnsignedChar *fmt = *format;
- while (SecIsDigit((SecInt)(int)(*fmt)) != 0) {
- 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->argPtr = NULL;
- spec->arrayWidth = 0;
- spec->number64 = 0;
- spec->number = 0;
- spec->numberWidth = SECUREC_NUM_WIDTH_INT; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */
- spec->numberArgType = 0; /* 1 for 64-bit integer, 0 otherwise */
- spec->width = 0;
- spec->widthSet = 0;
- spec->convChr = 0;
- spec->oriConvChr = 0;
- spec->isWCharOrLong = 0;
- spec->suppress = 0;
- #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
- spec->beyondMax = 0;
- #endif
- spec->negative = 0;
- spec->numberState = SECUREC_NUMBER_STATE_DEFAULT;
- }
- /*
- * Decode qualifier %I %L %h ...
- * Set finishFlag to 1 finish Flag
- */
- SECUREC_INLINE void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
- {
- switch (**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->numberArgType = 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->numberArgType = 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->numberArgType = 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 = SECUREC_TO_LOWERCASE(*fmt);
- if (!(ch == 'c' || ch == '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
- }
- }
- SECUREC_INLINE void SecDecodeClearArg(SecScanSpec *spec, va_list argList)
- {
- va_list argListSave; /* Backup for argList value, this variable don't need initialized */
- (void)SECUREC_MEMSET_FUNC_OPT(&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
- spec->argPtr = (void *)va_arg(argListSave, void *);
- /* Get the next argument, size of the array in characters */
- /* Use 0xffffffffUL mask to Support pass integer as array length */
- spec->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;
- }
- #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
- {
- SecScanSpec spec;
- int convChr = 0;
- const SecUnsignedChar *fmt = (const SecUnsignedChar *)format;
- /* 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) {
- return;
- }
- if (SecDecodeClearFormat(fmt, &convChr) != 0) {
- return;
- }
- if (*buffer != SECUREC_CHAR('\0') && convChr != 's') {
- /*
- * When buffer not empty just clear %s.
- * Example call sscanf by argment of (" \n", "%s", s, sizeof(s))
- */
- return;
- }
- SecDecodeClearArg(&spec, argList);
- /* There is no need to judge the upper limit */
- if (spec.arrayWidth == 0 || spec.argPtr == NULL) {
- return;
- }
- /* Clear one char */
- SecAddEndingZero(spec.argPtr, &spec);
- return;
- }
- /*
- * Assign number to output buffer
- */
- SECUREC_INLINE void SecAssignNumber(const SecScanSpec *spec)
- {
- void *argPtr = spec->argPtr;
- if (spec->numberArgType != 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 (int)((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) != 0) {
- 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)) {
- /* This code is specially converted to unsigned long type for compatibility */
- SecUnsignedInt64 number64As = (unsigned long)SECUREC_MAX_64BITS_VALUE - spec->number;
- if (number64As < (SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)SECUREC_CHAR('0')) {
- spec->beyondMax = 1;
- }
- }
- #endif
- spec->number += ((unsigned long)(SecUnsignedInt)spec->ch - (SecUnsignedInt)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 - (SecUnsignedInt)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 (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
- if (spec->number > SECUREC_MIN_LONG_NEG_VALUE) {
- spec->number = SECUREC_MIN_LONG_NEG_VALUE;
- } else {
- spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
- }
- if (spec->beyondMax != 0) {
- if (spec->numberWidth < SECUREC_NUM_WIDTH_INT) {
- spec->number = 0;
- }
- 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)(0U - spec->number); /* Wrap with unsigned long numbers */
- 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 (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
- #ifdef SECUREC_ON_64BITS
- if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
- if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) {
- spec->number = 0;
- } else {
- spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
- }
- }
- #else
- if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
- if ((spec->number > SECUREC_MIN_32BITS_NEG_VALUE)) {
- spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
- } else {
- spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
- }
- }
- #endif
- if (spec->beyondMax != 0) {
- #ifdef SECUREC_ON_64BITS
- if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
- spec->number = 0;
- }
- #else
- if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
- 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)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
- }
- #else
- spec->number = (unsigned int)(0U - (unsigned int)spec->number); /* Wrap with unsigned int numbers */
- #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 (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
- 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 (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
- #ifdef SECUREC_ON_64BITS
- if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH) != 0) {
- 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) != 0) {
- spec->number = (unsigned long)SECUREC_MAX_64BITS_VALUE;
- }
- #else
- if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
- if (spec->number > SECUREC_MAX_32BITS_POS_VALUE) {
- spec->number = SECUREC_MAX_32BITS_POS_VALUE;
- }
- }
- if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH) != 0) {
- 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 - (SecUnsignedInt)SECUREC_CHAR('0')) {
- spec->beyondMax = 1;
- }
- }
- #endif
- spec->number64 += ((SecUnsignedInt64)(SecUnsignedInt)spec->ch - (SecUnsignedInt)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 - (SecUnsignedInt)SECUREC_CHAR('0'));
- }
- #define SECUREC_DECODE_NUMBER_FUNC_NUM 2
- /*
- * Parse 64-bit integer formatted input, return 0 when ch is a number.
- */
- SECUREC_INLINE int SecDecodeNumber(SecScanSpec *spec)
- {
- /* Function name cannot add address symbol, causing 546 alarm */
- static void (* const secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
- SecDecodeNumberHex, SecDecodeNumber64Hex
- };
- static void (* const secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
- SecDecodeNumberOctal, SecDecodeNumber64Octal
- };
- static void (* const secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
- SecDecodeNumberDecimal, SecDecodeNumber64Decimal
- };
- if (spec->convChr == 'x' || spec->convChr == 'p') {
- if (SecIsXdigit(spec->ch) != 0) {
- (*secDecodeNumberHex[spec->numberArgType])(spec);
- } else {
- return -1;
- }
- return 0;
- }
- if (SecIsDigit(spec->ch) == 0) {
- return -1;
- }
- if (spec->convChr == 'o') {
- if (spec->ch < SECUREC_CHAR('8')) { /* Octal maximum limit '8' */
- (*secDecodeNumberOctal[spec->numberArgType])(spec);
- } else {
- return -1;
- }
- } else { /* The convChr is 'd' */
- (*secDecodeNumberDecimal[spec->numberArgType])(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 != 'p') {
- spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
- }
- #else
- spec->number = (unsigned long)(0U - spec->number); /* Wrap with unsigned long numbers */
- #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 (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
- if (spec->number64 > SECUREC_MIN_64BITS_NEG_VALUE) {
- spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
- } else {
- spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
- }
- if (spec->beyondMax != 0) {
- spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
- }
- } else { /* For o, u, x, X, p */
- spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
- if (spec->beyondMax != 0) {
- spec->number64 = SECUREC_MAX_64BITS_VALUE;
- }
- }
- } else {
- if (SECUREC_CONVERT_IS_SIGNED(spec->oriConvChr)) {
- 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 != 'p') {
- spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
- }
- #else
- spec->number64 = (SecUnsignedInt64)(0U - spec->number64); /* Wrap with unsigned int64 numbers */
- #endif
- }
- #endif
- return;
- }
- #if SECUREC_ENABLE_SCANF_FILE
- /*
- * Adjust the pointer position of the file stream
- */
- SECUREC_INLINE void SecSeekStream(SecFileStream *stream)
- {
- if (stream->count == 0) {
- if (feof(stream->pf) != 0) {
- /* File pointer at the end of file, don't need to seek back */
- stream->base[0] = '\0';
- return;
- }
- }
- /* Seek to original position, for file read, but nothing to input */
- if (fseek(stream->pf, stream->oriFilePos, SEEK_SET) != 0) {
- /* Seek failed, ignore it */
- stream->oriFilePos = 0;
- return;
- }
- if (stream->fileRealRead > 0) { /* Do not seek without input data */
- #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
- size_t residue = stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE;
- size_t loops;
- for (loops = 0; loops < (stream->fileRealRead / SECUREC_BUFFERED_BLOK_SIZE); ++loops) {
- if (fread(stream->base, (size_t)SECUREC_BUFFERED_BLOK_SIZE, (size_t)1, stream->pf) != (size_t)1) {
- break;
- }
- }
- if (residue != 0) {
- long curFilePos;
- if (fread(stream->base, residue, (size_t)1, stream->pf) != (size_t)1) {
- return;
- }
- curFilePos = ftell(stream->pf);
- if (curFilePos < stream->oriFilePos ||
- (size_t)(unsigned long)(curFilePos - stream->oriFilePos) < stream->fileRealRead) {
- /* Try to remedy the problem */
- long adjustNum = (long)(stream->fileRealRead - (size_t)(unsigned long)(curFilePos - stream->oriFilePos));
- (void)fseek(stream->pf, adjustNum, SEEK_CUR);
- }
- }
- #else
- /* Seek from oriFilePos. Regardless of the integer sign problem, call scanf will not read very large data */
- if (fseek(stream->pf, (long)stream->fileRealRead, SEEK_CUR) != 0) {
- /* Seek failed, ignore it */
- stream->oriFilePos = 0;
- return;
- }
- #endif
- }
- return;
- }
- /*
- * Adjust the pointer position of the file stream and free memory
- */
- SECUREC_INLINE void SecAdjustStream(SecFileStream *stream)
- {
- if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0 && 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)) != 0) {
- ++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)
- {
- #if SECUREC_HAVE_MBTOWC
- const SecUnsignedChar *fmt = *format;
- int ch1 = (int)spec->ch;
- int ch2 = SecGetChar(stream, &(spec->charCount));
- spec->ch = (SecInt)ch2;
- if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch2) {
- /* in console mode, ungetc twice may cause problem */
- SecUnGetChar(ch2, stream, &(spec->charCount));
- SecUnGetChar(ch1, stream, &(spec->charCount));
- return -1;
- }
- ++fmt;
- if ((unsigned int)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, &(spec->charCount));
- spec->ch = (SecInt)ch3;
- if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch3) {
- SecUnGetChar(ch3, stream, &(spec->charCount));
- return -1;
- }
- 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 */
- ++fmt;
- --spec->charCount;
- } else {
- SecUnGetChar(ch3, stream, &(spec->charCount));
- }
- }
- --spec->charCount; /* Only count as one character read */
- *format = fmt;
- return 0;
- #else
- SecUnGetChar(spec->ch, stream, &(spec->charCount));
- (void)format; /* To clear e438 last value assigned not used , the compiler will optimize this code */
- return -1;
- #endif
- }
- SECUREC_INLINE int SecFilterWcharInFormat(SecScanSpec *spec, const SecUnsignedChar **format, SecFileStream *stream)
- {
- if (SecIsLeadByte(spec->ch) != 0) {
- if (SecDecodeLeadByte(spec, format, stream) != 0) {
- return -1;
- }
- }
- return 0;
- }
- #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;
- #if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
- if (*fmt == SECUREC_CHAR('{')) {
- return -1;
- }
- #endif
- /* For building "table" data */
- ++fmt; /* Skip [ */
- bracketTable->mask = 0; /* Set all bits to 0 */
- if (*fmt == SECUREC_CHAR('^')) {
- ++fmt;
- bracketTable->mask = (unsigned char)0xffU; /* Use 0xffU to set all bits to 1 */
- }
- if (*fmt == SECUREC_CHAR(']')) {
- prevChar = SECUREC_CHAR(']');
- ++fmt;
- SecBracketSetBit(bracketTable->table, SECUREC_CHAR(']'));
- }
- while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
- SecUnsignedChar expCh = *fmt;
- ++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 */
- ++fmt;
- if (prevChar <= expCh) { /* %[a-z] %[a-a] */
- SecBracketSetBitRange(bracketTable->table, prevChar, expCh);
- } else {
- /* For %[z-a] */
- #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
- /* Swap start and end characters */
- SecBracketSetBitRange(bracketTable->table, expCh, prevChar);
- #else
- SecBracketSetBit(bracketTable->table, SECUREC_CHAR('-'));
- SecBracketSetBit(bracketTable->table, expCh);
- #endif
- }
- 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) != 0) {
- 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) != 0) {
- 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;
- ++di;
- 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)
- {
- static void (* const secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = {
- SecFinishNumber, SecFinishNumber64
- };
- while (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- spec->ch = SecGetChar(stream, &(spec->charCount));
- /* Decode ch to number */
- if (SecDecodeNumber(spec) != 0) {
- SecUnGetChar(spec->ch, stream, &(spec->charCount));
- break;
- }
- SECUREC_FILED_WIDTH_DEC(spec); /* Must be behind un get char, otherwise the logic is incorrect */
- spec->numberState = SECUREC_NUMBER_STATE_STARTED;
- }
- /* Handling integer negative numbers and beyond max */
- (*secFinishNumber[spec->numberArgType])(spec);
- if (spec->numberState == SECUREC_NUMBER_STATE_STARTED) {
- return 0;
- }
- return -1;
- }
- /*
- * Scan %d %i %o %u %x %p.
- * Return 0 OK
- */
- SECUREC_INLINE int SecInputNumber(SecFileStream *stream, SecScanSpec *spec)
- {
- /* Character already read */
- if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) {
- if (spec->ch == SECUREC_CHAR('-')) {
- spec->negative = 1;
- #if SECUREC_IN_KERNEL
- /* In kernel Refuse to enter negative number */
- if (SECUREC_CONVERT_IS_UNSIGNED(spec->oriConvChr)) {
- return -1;
- }
- #endif
- }
- SECUREC_FILED_WIDTH_DEC(spec); /* Do not need to check width here, must be greater than 0 */
- spec->ch = SecGetChar(stream, &(spec->charCount)); /* Eat + or - */
- spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next character, used for the '0' judgments */
- SecUnGetChar(spec->ch, stream, &(spec->charCount)); /* Not sure if it was actually read, so push back */
- }
- if (spec->oriConvChr == 'i') {
- spec->convChr = 'd'; /* The i could be d, o, or x, use d as default */
- }
- if (spec->ch == SECUREC_CHAR('0') && (spec->oriConvChr == 'x' || spec->oriConvChr == 'i') &&
- SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- /* Input string begin with 0, may be 0x123 0X123 0123 0x 01 0yy 09 0 0ab 00 */
- SECUREC_FILED_WIDTH_DEC(spec);
- spec->ch = SecGetChar(stream, &(spec->charCount)); /* ch is '0' */
- /* Read only '0' due to width limitation */
- if (!SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- /* The number or number64 in spec has been set 0 */
- return 0;
- }
- spec->ch = SecGetChar(stream, &(spec->charCount)); /* Get next char to check x or X, do not dec width */
- if ((SecChar)spec->ch == SECUREC_CHAR('x') || (SecChar)spec->ch == SECUREC_CHAR('X')) {
- spec->convChr = 'x';
- SECUREC_FILED_WIDTH_DEC(spec); /* Make incorrect width for x or X */
- } else {
- if (spec->oriConvChr == 'i') {
- spec->convChr = 'o';
- }
- /* For "0y" "08" "01" "0a" ... ,push the 'y' '8' '1' 'a' back */
- SecUnGetChar(spec->ch, stream, &(spec->charCount));
- /* Since 0 has been read, it indicates that a valid character has been read */
- spec->numberState = SECUREC_NUMBER_STATE_STARTED;
- }
- }
- 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 (SECUREC_FILED_WIDTH_ENOUGH(spec)) {
- SECUREC_FILED_WIDTH_DEC(spec);
- 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) != 0 ||
- SecCanInputString(spec->convChr, spec->ch) != 0 ||
- SecCanInputForBracket(spec->convChr, spec->ch, bracketTable) != 0)) {
- 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;
- }
- if ((spec->suppress != 0 && suppressed == 0) ||
- (spec->suppress == 0 && startPtr == spec->argPtr)) {
- /* No input was scanned */
- 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; /* Need to initialize to 0 */
- spec.charCount = 0; /* Need to initialize to 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)) != 0) {
- /* Read first no space char */
- spec.ch = SecSkipSpaceChar(stream, &(spec.charCount));
- /* Read the EOF cannot be returned directly here, because the case of " %n" needs to be handled */
- /* Put fist no space char backup. put EOF back is also OK, and to modify the character count */
- 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;
- }
- ++format;
- #if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)
- if (SecFilterWcharInFormat(&spec, &format, stream) != 0) {
- break;
- }
- #endif
- continue;
- }
- /* Now *format is % */
- /* Set default value for each % */
- SecSetDefaultScanSpec(&spec);
- if (SecDecodeScanFlag(&format, &spec) != 0) {
- formatError = 1;
- ++errRet;
- continue;
- }
- if (!SECUREC_FILED_WIDTH_ENOUGH(&spec)) {
- /* 0 width in format */
- ++errRet;
- continue;
- }
- /* Update wchar flag for %S %C */
- SecUpdateWcharFlagByType(*format, &spec);
- spec.convChr = SECUREC_TO_LOWERCASE(*format);
- spec.oriConvChr = spec.convChr; /* convChr may be modified to handle integer logic */
- if (spec.convChr != 'n') {
- if (spec.convChr != '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.oriConvChr) {
- case 'c': /* Also 'C' */
- if (spec.widthSet == 0) {
- spec.widthSet = 1;
- spec.width = 1;
- }
- /* fall-through */ /* FALLTHRU */
- case 's': /* Also 'S': */
- /* fall-through */ /* FALLTHRU */
- case SECUREC_BRACE:
- /* Unset last char to stream */
- SecUnGetChar(spec.ch, stream, &(spec.charCount));
- /* 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 */
- spec.arrayWidth = SECUREC_GET_ARRAYWIDTH(argList);
- 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 != '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 == SECUREC_BRACE) {
- /* Malloc when first %[ is meet for wchar version */
- #ifdef SECUREC_FOR_WCHAR
- if (SecAllocBracketTable(&bracketTable) != 0) {
- ++errRet;
- continue;
- }
- #endif
- (void)SECUREC_MEMSET_FUNC_OPT(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;
- }
- }
- /* Set completed. Now read string or character */
- if (SecInputString(stream, &spec, &bracketTable, &doneCount) != 0) {
- ++errRet;
- continue;
- }
- break;
- case 'p':
- /* Make %hp same as %p */
- spec.numberWidth = SECUREC_NUM_WIDTH_INT;
- #ifdef SECUREC_ON_64BITS
- spec.numberArgType = 1;
- #endif
- /* fall-through */ /* FALLTHRU */
- case 'o': /* fall-through */ /* FALLTHRU */
- case 'u': /* fall-through */ /* FALLTHRU */
- case 'd': /* fall-through */ /* FALLTHRU */
- case 'i': /* fall-through */ /* FALLTHRU */
- case '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 '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.numberArgType = 0;
- SecAssignNumber(&spec);
- }
- break;
- case 'e': /* fall-through */ /* FALLTHRU */
- case 'f': /* fall-through */ /* FALLTHRU */
- case 'g': /* Scan a float */
- /* Unset last char to stream */
- SecUnGetChar(spec.ch, stream, &(spec.charCount));
- #if SECUREC_ENABLE_SCANF_FLOAT
- 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;
- }
- if (SecAssignFloat(&floatSpec, &spec) != 0) {
- ++errRet;
- continue;
- }
- ++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 */
- }
- break;
- }
- ++match;
- ++format;
- }
- #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 != 0 || match != 0) ? doneCount : SECUREC_SCANF_EINVAL);
- }
- if (formatError != 0 || paraIsNull != 0) {
- /* Invalid Input Format or parameter, but not meet EOF */
- return SECUREC_SCANF_ERROR_PARA;
- }
- return doneCount;
- }
- #if SECUREC_ENABLE_SCANF_FILE
- /*
- * Get char from stream use std function
- */
- SECUREC_INLINE SecInt SecGetCharFromStream(const SecFileStream *stream)
- {
- SecInt ch;
- ch = SECUREC_GETC(stream->pf);
- return ch;
- }
- /*
- * Try to read the BOM header, when meet a BOM head, discard it, then data is Aligned to base
- */
- SECUREC_INLINE void SecReadAndSkipBomHeader(SecFileStream *stream)
- {
- /* Use size_t type conversion to clean e747 */
- stream->count = fread(stream->base, (size_t)1, (size_t)SECUREC_BOM_HEADER_SIZE, stream->pf);
- if (stream->count > SECUREC_BOM_HEADER_SIZE) {
- stream->count = 0;
- }
- if (SECUREC_BEGIN_WITH_BOM(stream->base, stream->count)) {
- /* It's BOM header, discard it */
- stream->count = 0;
- }
- }
- /*
- * Get char from file stream or buffer
- */
- SECUREC_INLINE SecInt SecGetCharFromFile(SecFileStream *stream)
- {
- SecInt ch;
- if (stream->count < sizeof(SecChar)) {
- /* Load file to buffer */
- size_t len;
- if (stream->base != NULL) {
- /* Put the last unread data in the buffer head */
- for (len = 0; len < stream->count; ++len) {
- stream->base[len] = stream->cur[len];
- }
- } else {
- 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 + sizeof(SecChar)); /* To store '\0' and aligned to wide char */
- if (stream->base == NULL) {
- return SECUREC_EOF;
- }
- /* First read file */
- if (stream->oriFilePos == 0) {
- /* Make sure the data is aligned to base */
- SecReadAndSkipBomHeader(stream);
- }
- }
- /* Skip existing data and read data */
- len = fread(stream->base + stream->count, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf);
- if (len > SECUREC_BUFFERED_BLOK_SIZE) { /* It won't happen, */
- 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 */
- }
- SECUREC_GET_CHAR(stream, &ch);
- if (ch != SECUREC_EOF) {
- stream->fileRealRead += sizeof(SecChar);
- }
- return ch;
- }
- #endif
- /*
- * Get char for wchar version
- */
- SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter)
- {
- *counter = *counter + 1; /* Always plus 1 */
- /* The main scenario is scanf str */
- if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) {
- SecInt ch;
- SECUREC_GET_CHAR(stream, &ch);
- return ch;
- }
- #if SECUREC_ENABLE_SCANF_FILE
- if ((stream->flag & SECUREC_FILE_STREAM_FLAG) != 0) {
- return SecGetCharFromFile(stream);
- }
- if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) {
- return SecGetCharFromStream(stream);
- }
- #endif
- return SECUREC_EOF;
- }
- /*
- * Unget Public realizatio char for wchar and char version
- */
- SECUREC_INLINE void SecUnGetCharImpl(SecInt ch, SecFileStream *stream)
- {
- if ((stream->flag & SECUREC_MEM_STR_FLAG) != 0) {
- SECUREC_UN_GET_CHAR(stream);
- return;
- }
- #if SECUREC_ENABLE_SCANF_FILE
- if ((stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) != 0) {
- SECUREC_UN_GET_CHAR(stream);
- if (stream->fileRealRead > 0) {
- stream->fileRealRead -= sizeof(SecChar);
- }
- return;
- }
- if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) != 0) {
- (void)SECUREC_UN_GETC(ch, stream->pf);
- return;
- }
- #else
- (void)ch; /* To clear e438 last value assigned not used , the compiler will optimize this code */
- #endif
- }
- /*
- * Unget char for char version
- */
- SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter)
- {
- *counter = *counter - 1; /* Always mius 1 */
- if (ch != SECUREC_EOF) {
- SecUnGetCharImpl(ch, stream);
- }
- }
- /*
- * Skip space char by isspace
- */
- SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter)
- {
- SecInt ch;
- do {
- ch = SecGetChar(stream, counter);
- if (ch == SECUREC_EOF) {
- break;
- }
- } while (SecIsSpace(ch) != 0);
- return ch;
- }
- #endif /* INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 */
|