1/** 2 * Copyright 2020 Huawei Technologies Co., Ltd 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 18#define OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 19 20#define SECUREC_NULL_STRING_SIZE 8 21#define SECUREC_STATE_TABLE_SIZE 337 22#define SECUREC_OFFSET_BITS_WORD 16 23#define SECUREC_OFFSET_BITS_DWORD 32 24 25#define SECUREC_OFFSET_DIV_OCTAL 3 26#define SECUREC_OFFSET_DIV_HEX 4 27#define SECUREC_RADIX_OCTAL 8 28#define SECUREC_RADIX_DECIMAL 10 29#define SECUREC_RADIX_HEX 16 30/* Use two displacements to eliminate compilation warnings */ 31#define SECUREC_SHR_DWORD(x) (((x) >> 16) >> 16) 32#define SECUREC_PREFIX_LEN 2 33/* size include '+' and '\0' */ 34#define SECUREC_FLOAT_BUF_EXT 2 35 36 37#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K 38#define SECUREC_FMT_STR_LEN 8 39#else 40#define SECUREC_FMT_STR_LEN 16 41#endif 42 43typedef struct { 44 unsigned int flags; 45 int fldWidth; 46 int precision; 47 int bufferIsWide; /* flag for buffer contains wide chars ;0 is not wide char */ 48 int dynWidth; /* %* 1 width from variable parameter ;0 not */ 49 int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ 50} SecFormatAttr; 51 52typedef union { 53 char *str; /* not a null terminated string */ 54#if SECUREC_HAVE_WCHART 55 wchar_t *wStr; 56#endif 57} SecFormatBuf; 58 59typedef union { 60 char str[SECUREC_BUFFER_SIZE + 1]; 61#ifdef SECUREC_FOR_WCHAR 62 wchar_t wStr[SECUREC_BUFFER_SIZE + 1]; 63#endif 64} SecBuffer; 65 66#if SECUREC_ENABLE_SPRINTF_FLOAT 67/* call system sprintf to format float value */ 68static int SecIndirectSprintf(char *strDest, const char *format, ...) 69{ 70 int ret; /* If initialization causes e838 */ 71 va_list argList; 72 73 va_start(argList, format); 74 SECUREC_MASK_MSVC_CRT_WARNING 75 ret = vsprintf(strDest, format, argList); 76 SECUREC_END_MASK_MSVC_CRT_WARNING 77 va_end(argList); 78 (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ 79 80 return ret; 81} 82 83#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 84/* out put long double value to dest */ 85static int SecFormatLongDboule(char *strDest,const SecFormatAttr *formatAttr, const char *fmt, long double ldValue) 86{ 87 int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth); 88 if (formatAttr->dynWidth && formatAttr->dynPrecision) { 89 return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, ldValue); 90 } else if (formatAttr->dynWidth) { 91 return SecIndirectSprintf(strDest, fmt, fldWidth, ldValue); 92 } else if (formatAttr->dynPrecision) { 93 return SecIndirectSprintf(strDest, fmt, formatAttr->precision, ldValue); 94 } 95 return SecIndirectSprintf(strDest, fmt, ldValue); 96} 97#endif 98 99/* out put double value to dest */ 100static int SecFormatDboule(char *strDest, const SecFormatAttr *formatAttr, const char *fmt, double dValue) 101{ 102 int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth); 103 if (formatAttr->dynWidth && formatAttr->dynPrecision) { 104 return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, dValue); 105 } else if (formatAttr->dynWidth) { 106 return SecIndirectSprintf(strDest, fmt, fldWidth, dValue); 107 } else if (formatAttr->dynPrecision) { 108 return SecIndirectSprintf(strDest, fmt, formatAttr->precision, dValue); 109 } 110 return SecIndirectSprintf(strDest, fmt, dValue); 111} 112#endif 113 114#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 115/* to clear e506 warning */ 116static int SecIsSameSize(size_t sizeA, size_t sizeB) 117{ 118 return sizeA == sizeB; 119} 120#endif 121 122#define SECUREC_SPECIAL_DWORD(val32, numBase) do { \ 123 --formatBuf.str; \ 124 *(formatBuf.str) = digits[(val32) % (numBase)]; \ 125} while (((val32) /= (numBase)) != 0) 126 127#if defined(SECUREC_USE_SPECIAL_DIV64) || (defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)) 128/* 129 * Fast divide by 10 algorithm. 130 * Calculation divisor multiply 0xcccccccccccccccdULL, resultHi64 >> 3 as quotient 131 */ 132static void SecU64Div10(SecUnsignedInt64 divisor, SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder) 133{ 134 SecUnsignedInt64 mask = 0xffffffffULL; /* use 0xffffffffULL as 32 bit mask */ 135 SecUnsignedInt64 magicHi = 0xccccccccULL; /* fast divide 10 magic numbers high 32bit 0xccccccccULL */ 136 SecUnsignedInt64 magicLow = 0xcccccccdULL; /* fast divide 10 magic numbers low 32bit 0xcccccccdULL */ 137 SecUnsignedInt64 divisorHi = (SecUnsignedInt64)(SECUREC_SHR_DWORD(divisor)); /* hig 32 bit use */ 138 SecUnsignedInt64 divisorLow = (SecUnsignedInt64)(divisor & mask); /* low 32 bit mask */ 139 SecUnsignedInt64 factorHi = divisorHi * magicHi; 140 SecUnsignedInt64 factorLow1 = divisorHi * magicLow; 141 SecUnsignedInt64 factorLow2 = divisorLow * magicHi; 142 SecUnsignedInt64 factorLow3 = divisorLow * magicLow; 143 SecUnsignedInt64 carry = (factorLow1 & mask) + (factorLow2 & mask) + SECUREC_SHR_DWORD(factorLow3); 144 SecUnsignedInt64 resultHi64 = factorHi + SECUREC_SHR_DWORD(factorLow1) + \ 145 SECUREC_SHR_DWORD(factorLow2) + SECUREC_SHR_DWORD(carry); 146 147 *quotient = resultHi64 >> 3; /* fast divide 10 magic numbers 3 */ 148 *remainder = (SecUnsignedInt32)(divisor - ((*quotient) * 10)); /* quotient mul 10 */ 149 return; 150} 151#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) 152/* 153 * Divide function for VXWORKS 154 */ 155static int SecU64Div32(SecUnsignedInt64 divisor, SecUnsignedInt32 radix, 156 SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder) 157{ 158 switch (radix) { 159 case SECUREC_RADIX_DECIMAL: 160 SecU64Div10(divisor, quotient, remainder); 161 break; 162 case SECUREC_RADIX_HEX: 163 *quotient = divisor >> SECUREC_OFFSET_DIV_HEX; 164 *remainder = divisor & 0xfULL; /* mask one hex number by 0xfULL */ 165 break; 166 case SECUREC_RADIX_OCTAL: 167 *quotient = divisor >> SECUREC_OFFSET_DIV_OCTAL; 168 *remainder = divisor & 0x7ULL; /* mask one hex number by 0x7ULL */ 169 break; 170 default: 171 return -1; 172 } 173 return 0; 174} 175#endif 176#endif 177 178#if defined(SECUREC_USE_SPECIAL_DIV64) 179/* The compiler does not provide 64 bit division problems */ 180#define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \ 181 SecUnsignedInt64 quotient = 0; \ 182 SecUnsignedInt32 digit = 0; \ 183 SecU64Div10((val64), &(quotient), &(digit)); \ 184 --formatBuf.str; \ 185 *(formatBuf.str) = digits[digit]; \ 186 (val64) = quotient; \ 187} while ((val64) != 0) 188#else 189#define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \ 190 --formatBuf.str; \ 191 *(formatBuf.str) = digits[(val64) % SECUREC_RADIX_DECIMAL]; \ 192} while (((val64) /= SECUREC_RADIX_DECIMAL) != 0) 193#endif 194#define SECUREC_SPECIAL_QWORD(val64, numBase) do { \ 195 --formatBuf.str; \ 196 *(formatBuf.str) = digits[(val64) % (numBase)]; \ 197} while (((val64) /= (numBase)) != 0) 198 199 200#define SECUREC_SAFE_WRITE_STR_OPT(src, txtLen, outStream, outChars) do { \ 201 int ii_; \ 202 for (ii_ = 0; ii_ < (txtLen); ++ii_) { \ 203 *((SecChar *)(void *)((outStream)->cur)) = *(SecChar *)(src); \ 204 (outStream)->cur += sizeof(SecChar); \ 205 (src) = (src) + 1; \ 206 } \ 207 (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \ 208 *(outChars) = *(outChars) + (txtLen); \ 209} SECUREC_WHILE_ZERO 210 211#define SECUREC_SAFE_WRITE_STR(src, txtLen, outStream, outChars) do { \ 212 if ((txtLen) < 12) { /* performance optimization for mobile number length 12 */ \ 213 SECUREC_SAFE_WRITE_STR_OPT((src), (txtLen), (outStream), (outChars)); \ 214 } else { \ 215 SecDoMemcpy((outStream)->cur, (src), ((size_t)(unsigned int)(txtLen) * (sizeof(SecChar)))); \ 216 (outStream)->cur += (size_t)((size_t)(unsigned int)(txtLen) * (sizeof(SecChar))); \ 217 (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \ 218 *(outChars) = *(outChars) + (txtLen); \ 219 } \ 220} SECUREC_WHILE_ZERO 221 222#define SECUREC_SAFE_WRITE_CHAR(c, outStream, outChars) do { \ 223 *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(c); \ 224 (outStream)->cur += sizeof(SecChar); \ 225 (outStream)->count -= (int)(sizeof(SecChar)); \ 226 *(outChars) = *(outChars) + 1; \ 227} SECUREC_WHILE_ZERO 228 229#define SECUREC_SAFE_PADDING(padChar, padLen, outStream, outChars) do { \ 230 int ii_; \ 231 for (ii_ = 0; ii_ < (padLen); ++ii_) { \ 232 *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(padChar); \ 233 (outStream)->cur += sizeof(SecChar); \ 234 } \ 235 (outStream)->count -= (padLen) * (int)(sizeof(SecChar)); \ 236 *(outChars) = *(outChars) + (padLen); \ 237} SECUREC_WHILE_ZERO 238 239/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */ 240#define SECUREC_IS_REST_BUF_ENOUGH(stream, needLen) ((int)((stream)->count - \ 241 (int)(needLen) * (int)(sizeof(SecChar))) >= 0) 242 243#define SECUREC_FMT_STATE_OFFSET 256 244#ifdef SECUREC_FOR_WCHAR 245#define SECUREC_FMT_TYPE(c, fmtTable) ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \ 246 ((fmtTable)[(unsigned char)(c)]) : 0) 247#define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)((((fmtTable)[(SECUREC_FMT_TYPE(c, (fmtTable))) * \ 248 ((unsigned char)STAT_INVALID + 1) + \ 249 (unsigned char)(lastState) + \ 250 SECUREC_FMT_STATE_OFFSET]))) 251#else 252#define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)(((fmtTable)[((fmtTable)[(unsigned char)(c)]) * \ 253 ((unsigned char)STAT_INVALID + 1) + \ 254 (unsigned char)(lastState) + \ 255 SECUREC_FMT_STATE_OFFSET])) 256#endif 257 258static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) 259{ 260 switch (ch) { 261 case SECUREC_CHAR(' '): 262 attr->flags |= SECUREC_FLAG_SIGN_SPACE; 263 break; 264 case SECUREC_CHAR('+'): 265 attr->flags |= SECUREC_FLAG_SIGN; 266 break; 267 case SECUREC_CHAR('-'): 268 attr->flags |= SECUREC_FLAG_LEFT; 269 break; 270 case SECUREC_CHAR('0'): 271 attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */ 272 break; 273 case SECUREC_CHAR('#'): 274 attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */ 275 break; 276 default: 277 break; 278 } 279 return; 280} 281 282 283/* 284 * Decoded size identifier in format string to Reduce the number of lines of function code 285 */ 286static int SecDecodeSizeI(SecFormatAttr *attr, const SecChar **format) 287{ 288#ifdef SECUREC_ON_64BITS 289 attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */ 290#endif 291 if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) { 292 (*format) += 2; /* add 2 to skip I64 */ 293 attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */ 294 } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) { 295 (*format) += 2; /* add 2 to skip I32 */ 296 attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */ 297 } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) || 298 (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || 299 (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) { 300 /* do nothing */ 301 } else { 302 /* Compatibility code for "%I" just print I */ 303 return -1; 304 } 305 return 0; 306} 307/* 308 * Decoded size identifier in format string 309 */ 310static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) 311{ 312 switch (ch) { 313#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 314 case SECUREC_CHAR('j'): 315 attr->flags |= SECUREC_FLAG_INTMAX; 316 break; 317#endif 318 case SECUREC_CHAR('q'): 319 /* fall-through */ /* FALLTHRU */ 320 case SECUREC_CHAR('L'): 321 attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE; 322 break; 323 case SECUREC_CHAR('l'): 324 if (**format == SECUREC_CHAR('l')) { 325 *format = *format + 1; 326 attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */ 327 } else { 328 attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */ 329 } 330 break; 331 case SECUREC_CHAR('t'): 332 attr->flags |= SECUREC_FLAG_PTRDIFF; 333 break; 334#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 335 case SECUREC_CHAR('z'): 336 /* fall-through */ /* FALLTHRU */ 337 case SECUREC_CHAR('Z'): 338 attr->flags |= SECUREC_FLAG_SIZE; 339 break; 340#endif 341 case SECUREC_CHAR('I'): 342 if (SecDecodeSizeI(attr, format) != 0) { 343 /* Compatibility code for "%I" just print I */ 344 return -1; 345 } 346 break; 347 case SECUREC_CHAR('h'): 348 if (**format == SECUREC_CHAR('h')) { 349 attr->flags |= SECUREC_FLAG_CHAR; /* char */ 350 } else { 351 attr->flags |= SECUREC_FLAG_SHORT; /* short int */ 352 } 353 break; 354 case SECUREC_CHAR('w'): 355 attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */ 356 break; 357 default: 358 break; 359 } 360 return 0; 361} 362 363/* 364 * Decoded char type identifier 365 */ 366static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer) 367{ 368#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS)) 369 attr->flags &= ~SECUREC_FLAG_LEADZERO; 370#endif 371 372#ifdef SECUREC_FOR_WCHAR 373 attr->bufferIsWide = 1; 374 if (attr->flags & SECUREC_FLAG_SHORT) { 375#if SECUREC_HAVE_MBTOWC 376 /* multibyte character to wide character */ 377 char tmpChar[2]; /* One character string, length is 2 */ 378 tmpChar[0] = (char)(cValue & 0x00ff); 379 tmpChar[1] = '\0'; 380 381 if (mbtowc(buffer->wStr, tmpChar, sizeof(tmpChar)) < 0) { 382 return -1; 383 } 384#else 385 return -1; 386#endif 387 } else { 388 buffer->wStr[0] = (wchar_t)cValue; 389 } 390 formatBuf->wStr = buffer->wStr; 391 return 1; /* only 1 wide character */ 392#else /* SECUREC_FOR_WCHAR */ 393 attr->bufferIsWide = 0; 394 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { 395#if SECUREC_HAVE_WCTOMB 396 wchar_t wChar = (wchar_t)cValue; 397 int textLen; 398 /* wide character to multibyte character */ 399 SECUREC_MASK_MSVC_CRT_WARNING 400 textLen = wctomb(buffer->str, wChar); 401 SECUREC_END_MASK_MSVC_CRT_WARNING 402 if (textLen < 0) { 403 return -1; 404 } 405 formatBuf->str = buffer->str; 406 return textLen; 407#else 408 return -1; 409#endif 410 } else { 411 /* get multibyte character from argument */ 412 unsigned short temp; 413 temp = (unsigned short)cValue; 414 buffer->str[0] = (char)temp; 415 formatBuf->str = buffer->str; 416 return 1; /* only 1 character */ 417 } 418#endif 419 420} 421 422/* literal string to print null ptr, define it as array rather than const text area 423 * is to avoid gcc warning with pointing const text with variable 424 */ 425#if SECUREC_HAVE_WCHART 426static wchar_t g_wStrNullString[SECUREC_NULL_STRING_SIZE] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; 427#endif 428static char g_strNullString[SECUREC_NULL_STRING_SIZE] = "(null)"; 429 430static int SecDecodeTypeSchar(const SecFormatAttr *attr, SecFormatBuf *formatBuf) 431{ 432 int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; 433 int textLen; 434 435 if (formatBuf->str == NULL) { /* NULL passed, use special string */ 436 formatBuf->str = g_strNullString; 437 } 438 if (finalPrecision == SECUREC_INT_MAX) { 439 /* precision NOT assigned */ 440 /* The strlen performance is high when the string length is greater than 32 */ 441 textLen = (int)strlen(formatBuf->str); 442 } else { 443 /* precision assigned */ 444 size_t tmpLen; 445 SECUREC_CALC_STR_LEN(formatBuf->str, (size_t)(unsigned int)finalPrecision, &tmpLen); 446 textLen = (int)tmpLen; 447 } 448 return textLen; 449} 450 451#if SECUREC_HAVE_WCHART 452static int SecDecodeTypeSwchar(SecFormatAttr *attr, SecFormatBuf *formatBuf) 453{ 454 int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; 455 int textLen; 456 457 attr->bufferIsWide = 1; 458 if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ 459 formatBuf->wStr = g_wStrNullString; 460 } 461 /* textLen in wchar_t */ 462 SECUREC_CALC_WSTR_LEN(formatBuf->wStr, finalPrecision, &textLen); 463 464 return textLen; 465} 466#endif 467 468/* 469 * Decoded string identifier 470 */ 471static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf) 472{ 473 int textLen; 474#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX)) 475 attr->flags &= ~SECUREC_FLAG_LEADZERO; 476#endif 477 formatBuf->str = argPtr; 478#ifdef SECUREC_FOR_WCHAR 479#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) 480 if (!(attr->flags & SECUREC_FLAG_LONG)) { 481 attr->flags |= SECUREC_FLAG_SHORT; 482 } 483#endif 484 if (attr->flags & SECUREC_FLAG_SHORT) { 485 /* textLen now contains length in multibyte chars */ 486 textLen = SecDecodeTypeSchar(attr, formatBuf); 487 } else { 488 /* textLen now contains length in wide chars */ 489 textLen = SecDecodeTypeSwchar(attr, formatBuf); 490 } 491#else /* SECUREC_FOR_WCHAR */ 492 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { 493 /* textLen now contains length in wide chars */ 494#if SECUREC_HAVE_WCHART 495 textLen = SecDecodeTypeSwchar(attr, formatBuf); 496#else 497 textLen = 0; 498#endif 499 } else { 500 /* textLen now contains length in multibyte chars */ 501 textLen = SecDecodeTypeSchar(attr, formatBuf); 502 } 503#endif /* SECUREC_FOR_WCHAR */ 504 return textLen; 505} 506 507/* 508 * Write one character to dest buffer 509 */ 510static void SecOutputOneChar(SecChar ch, SecPrintfStream *stream, int *counter) 511{ 512 /* normal state, write character */ 513 if (SECUREC_IS_REST_BUF_ENOUGH(stream, 1)) { /* only one char */ 514 SECUREC_SAFE_WRITE_CHAR(ch, stream, counter); /* char * cast to wchar * */ 515 } else { 516#ifdef SECUREC_FOR_WCHAR 517 SecWriteCharW(ch, stream, counter); 518#else 519 /* optimize function call to code */ 520 *counter = -1; 521 stream->count = -1; 522#endif 523 } 524} 525 526/* 527 * Check precison in format 528 */ 529static int SecDecodePrecision(SecChar ch, SecFormatAttr *formatAttr) 530{ 531 if (formatAttr->dynPrecision == 0) { 532 /* add digit to current precision */ 533 if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->precision)) { 534 return -1; 535 } 536 formatAttr->precision = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->precision) + 537 (unsigned char)(ch - SECUREC_CHAR('0')); 538 } else { 539 if (formatAttr->precision < 0) { 540 formatAttr->precision = -1; 541 } 542 if (formatAttr->precision > SECUREC_MAX_WIDTH_LEN) { 543 return -1; 544 } 545 } 546 return 0; 547} 548 549 550/* 551 * Check width in format 552 */ 553static int SecDecodeWidth(SecChar ch, SecFormatAttr *formatAttr, SecFmtState lastState) 554{ 555 if (formatAttr->dynWidth == 0) { 556 if (lastState != STAT_WIDTH) { 557 formatAttr->fldWidth = 0; 558 } 559 if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->fldWidth)) { 560 return -1; 561 } 562 formatAttr->fldWidth = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->fldWidth) + 563 (unsigned char)(ch - SECUREC_CHAR('0')); 564 } else { 565 if (formatAttr->fldWidth < 0) { 566 formatAttr->flags |= SECUREC_FLAG_LEFT; 567 formatAttr->fldWidth = (-formatAttr->fldWidth); 568 if (formatAttr->fldWidth > SECUREC_MAX_WIDTH_LEN) { 569 return -1; 570 } 571 } 572 } 573 return 0; 574} 575#ifdef SECUREC_FOR_WCHAR 576/* 577 * Formatting output core functions for wchar version.Called by a function such as vswprintf_s 578 * argList must not be declare as const 579 */ 580static int SecOutputSW(SecPrintfStream *stream, const wchar_t *cFormat, va_list argList) 581#else 582/* 583 * Formatting output core functions for char version.Called by a function such as vsnprintf_s 584 */ 585static int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argList) 586#endif 587{ 588 const SecChar *format = cFormat; 589#if SECUREC_ENABLE_SPRINTF_FLOAT 590 char *floatBuf = NULL; 591#endif 592 SecFormatBuf formatBuf; 593 static const char *itoaUpperDigits = "0123456789ABCDEFX"; 594 static const char *itoaLowerDigits = "0123456789abcdefx"; 595 const char *digits = itoaUpperDigits; 596 unsigned int radix = SECUREC_RADIX_DECIMAL; 597 int charsOut; /* characters written */ 598 int prefixLen = 0; /* Must be initialized or compiler alerts */ 599 int padding = 0; 600 int textLen; /* length of the text */ 601 int noOutput = 0; /* Must be initialized or compiler alerts */ 602 SecFmtState state; 603 SecFmtState lastState; 604 SecChar prefix[SECUREC_PREFIX_LEN] = { 0 }; 605 SecChar ch; /* currently read character */ 606 static const unsigned char stateTable[SECUREC_STATE_TABLE_SIZE] = { 607 /* type 0: nospecial meanin; 608 * 1: '%'; 609 * 2: '.' 610 * 3: '*' 611 * 4: '0' 612 * 5: '1' ... '9' 613 * 6: ' ', '+', '-', '#' 614 * 7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j' 615 * 8: 'd','o','u','i','x','X','e','f','g' 616 */ 617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 619 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, 620 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 621 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 622 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 623 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, 624 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 625 /* fill zero for normal char 128 byte for 0x80 - 0xff */ 626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 634 /* state 0: normal 635 * 1: percent 636 * 2: flag 637 * 3: width 638 * 4: dot 639 * 5: precis 640 * 6: size 641 * 7: type 642 * 8: invalid 643 */ 644 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 645 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, 646 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 647 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 648 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 649 0x00 650 }; 651 652 SecFormatAttr formatAttr; 653 SecBuffer buffer; 654 formatAttr.flags = 0; 655 formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */ 656 formatAttr.fldWidth = 0; 657 formatAttr.precision = 0; 658 formatAttr.dynWidth = 0; 659 formatAttr.dynPrecision = 0; 660 charsOut = 0; 661 textLen = 0; 662 state = STAT_NORMAL; /* starting state */ 663 formatBuf.str = NULL; 664 665 /* loop each format character */ 666 /* remove format != NULL */ 667 while ((ch = *format) != SECUREC_CHAR('\0') && charsOut >= 0) { 668 ++format; 669 lastState = state; 670 state = SECUREC_DECODE_STATE(ch, stateTable, lastState); 671 switch (state) { 672 case STAT_NORMAL: 673 SecOutputOneChar(ch, stream, &charsOut); 674 continue; 675 case STAT_PERCENT: 676 /* set default values */ 677 prefixLen = 0; 678 noOutput = 0; 679 formatAttr.flags = 0; 680 formatAttr.fldWidth = 0; 681 formatAttr.precision = -1; 682 formatAttr.bufferIsWide = 0; 683 formatAttr.dynWidth = 0; 684 formatAttr.dynPrecision = 0; 685 break; 686 case STAT_FLAG: 687 /* set flag based on which flag character */ 688 SecDecodeFlags(ch, &formatAttr); 689 break; 690 case STAT_WIDTH: 691 /* update width value */ 692 if (ch == SECUREC_CHAR('*')) { 693 /* get width */ 694 formatAttr.fldWidth = (int)va_arg(argList, int); 695 formatAttr.dynWidth = 1; 696 } else { 697 formatAttr.dynWidth = 0; 698 } 699 if (SecDecodeWidth(ch, &formatAttr, lastState) != 0) { 700 return -1; 701 } 702 break; 703 case STAT_DOT: 704 formatAttr.precision = 0; 705 break; 706 case STAT_PRECIS: 707 /* update precison value */ 708 if (ch == SECUREC_CHAR('*')) { 709 /* get precision from arg list */ 710 formatAttr.precision = (int)va_arg(argList, int); 711 formatAttr.dynPrecision = 1; 712 } else { 713 formatAttr.dynPrecision = 0; 714 } 715 if (SecDecodePrecision(ch, &formatAttr) != 0) { 716 return -1; 717 } 718 break; 719 case STAT_SIZE: 720 /* read a size specifier, set the formatAttr.flags based on it */ 721 if (SecDecodeSize(ch, &formatAttr, &format) != 0) { 722 /* Compatibility code for "%I" just print I */ 723 SecOutputOneChar(ch, stream, &charsOut); 724 state = STAT_NORMAL; 725 continue; 726 } 727 break; 728 case STAT_TYPE: 729 switch (ch) { 730 case SECUREC_CHAR('C'): 731 /* wide char */ 732 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 733#ifdef SECUREC_FOR_WCHAR 734 formatAttr.flags |= SECUREC_FLAG_SHORT; 735#else 736 formatAttr.flags |= SECUREC_FLAG_WIDECHAR; 737#endif 738 } 739 /* fall-through */ 740 /* FALLTHRU */ 741 case SECUREC_CHAR('c'): 742 do { 743 unsigned int cValue = (unsigned int)va_arg(argList, int); 744 textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer); 745 if (textLen < 0) { 746 noOutput = 1; 747 } 748 } SECUREC_WHILE_ZERO; 749 break; 750 case SECUREC_CHAR('S'): /* wide char string */ 751 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 752#ifndef SECUREC_FOR_WCHAR 753 formatAttr.flags |= SECUREC_FLAG_WIDECHAR; 754#else 755 formatAttr.flags |= SECUREC_FLAG_SHORT; 756#endif 757 } 758 /* fall-through */ 759 /* FALLTHRU */ 760 case SECUREC_CHAR('s'): 761 do { 762 char *argPtr = (char *)va_arg(argList, char *); 763 textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf); 764 } SECUREC_WHILE_ZERO; 765 break; 766 case SECUREC_CHAR('n'): 767 /* higher risk disable it */ 768 return -1; 769 case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ 770 case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ 771 case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ 772 case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */ 773 /* convert format char to lower , use Explicit conversion to clean up compilation warning */ 774 ch = (SecChar)(ch + ((SecChar)(SECUREC_CHAR('a')) - (SECUREC_CHAR('A')))); 775 /* fall-through */ 776 /* FALLTHRU */ 777 case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ 778 case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */ 779 case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ 780 case SECUREC_CHAR('a'): 781#if SECUREC_ENABLE_SPRINTF_FLOAT 782 do { 783 int bufferSize = 0; /* size of formatBuf.str */ 784 /* floating point conversion */ 785 formatBuf.str = buffer.str; /* output buffer for float string with default size */ 786 787 /* compute the precision value */ 788 if (formatAttr.precision < 0) { 789 formatAttr.precision = SECUREC_FLOAT_DEFAULT_PRECISION; 790 } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) { 791 formatAttr.precision = 1; 792 } 793 794 /* calc buffer size to store double value 795 * The maximum length of SECUREC_MAX_WIDTH_LEN is enough 796 */ 797 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 798 if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE_LB)) { 799 noOutput = 1; 800 break; 801 } 802 /* Long double needs to meet the basic print length */ 803 bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision + SECUREC_FLOAT_BUF_EXT; 804 } else { 805 if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE)) { 806 noOutput = 1; 807 break; 808 } 809 /* Double needs to meet the basic print length */ 810 bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision + SECUREC_FLOAT_BUF_EXT; 811 } 812 if (formatAttr.fldWidth > bufferSize) { 813 bufferSize = formatAttr.fldWidth + SECUREC_FLOAT_BUF_EXT; 814 } 815 816 if (bufferSize > SECUREC_BUFFER_SIZE) { 817 /* the current vlaue of SECUREC_BUFFER_SIZE could NOT store the 818 * formatted float string 819 */ 820 floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize)); 821 if (floatBuf != NULL) { 822 formatBuf.str = floatBuf; 823 } else { 824 noOutput = 1; 825 break; 826 } 827 } 828 829 do { 830 /* add following code to call system sprintf API for float number */ 831 const SecChar *pFloatFmt = format - 2; /* sub 2 to the position before 'f' or 'g' */ 832 int k; 833 int fFmtStrLen; 834 char fFmtBuf[SECUREC_FMT_STR_LEN]; 835 char *fFmtStr = fFmtBuf; 836 char *fFmtHeap = NULL; /* to clear warning */ 837 838 while (SECUREC_CHAR('%') != *pFloatFmt) { /* must meet '%' */ 839 --pFloatFmt; 840 } 841 fFmtStrLen = (int)((format - pFloatFmt) + 1); /* with ending terminator */ 842 if (fFmtStrLen > SECUREC_FMT_STR_LEN) { 843 /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */ 844 fFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fFmtStrLen)); 845 if (fFmtHeap == NULL) { 846 noOutput = 1; 847 break; 848 } else { 849 for (k = 0; k < fFmtStrLen - 1; ++k) { 850 /* convert wchar to char */ 851 fFmtHeap[k] = (char)(pFloatFmt[k]); /* copy the format string */ 852 } 853 fFmtHeap[k] = '\0'; 854 855 fFmtStr = fFmtHeap; 856 } 857 } else { 858 /* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */ 859 for (k = 0; k < fFmtStrLen - 1; ++k) { 860 /* convert wchar to char */ 861 fFmtBuf[k] = (char)(pFloatFmt[k]); /* copy the format string */ 862 } 863 fFmtBuf[k] = '\0'; 864 } 865 866 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 867#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 868 long double tmp = (long double)va_arg(argList, long double); 869 textLen = SecFormatLongDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); 870#else 871 double tmp = (double)va_arg(argList, double); 872 textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); 873#endif 874 } else { 875 double tmp = (double)va_arg(argList, double); 876 textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); 877 } 878 879 if (fFmtHeap != NULL) { 880 /* if buffer is alloced on heap, free it */ 881 SECUREC_FREE(fFmtHeap); 882 fFmtHeap = NULL; 883 /* to clear e438 last value assigned not used , the compiler will 884 * optimize this code 885 */ 886 (void)fFmtHeap; 887 } 888 if (textLen < 0 || textLen >= bufferSize) { 889 /* bufferSize is large enough, just validation the return value */ 890 noOutput = 1; 891 break; 892 } 893 894 /* no padding ,this variable to calculate amount of padding */ 895 formatAttr.fldWidth = textLen; 896 prefixLen = 0; /* no padding ,this variable to calculate amount of padding */ 897 formatAttr.flags = 0; /* clear all internal formatAttr.flags */ 898 break; 899 } SECUREC_WHILE_ZERO; 900 } SECUREC_WHILE_ZERO; 901 break; 902#else 903 return -1; 904#endif 905 case SECUREC_CHAR('p'): /* fall-through */ /* FALLTHRU */ 906 case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ 907 case SECUREC_CHAR('x'): 908 /* unsigned lower hex output */ 909 digits = itoaLowerDigits; 910 radix = SECUREC_RADIX_HEX; 911 switch (ch) { 912 case SECUREC_CHAR('p'): 913 /* print a pointer */ 914#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 915 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 916#else 917 formatAttr.flags |= SECUREC_FLAG_POINTER; 918#endif 919#ifdef SECUREC_ON_64BITS 920 formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */ 921#else 922 formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */ 923#endif 924 925#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) 926#if defined(SECUREC_VXWORKS_PLATFORM) 927 formatAttr.precision = 1; 928#else 929 formatAttr.precision = 0; 930#endif 931 formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ 932 break; 933#else 934 /* not linux vxwoks */ 935#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 936 formatAttr.precision = 1; 937#else 938 formatAttr.precision = 2 * sizeof(void *); /* 2 precision of different systems */ 939#endif 940#endif 941 942#if defined(SECUREC_ON_UNIX) 943 break; 944#endif 945 /* fall-through */ /* FALLTHRU */ 946 case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ 947 /* unsigned upper hex output */ 948 digits = itoaUpperDigits; 949 break; 950 default: 951 break; 952 } 953 954 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { 955 /* alternate form means '0x' prefix */ 956 prefix[0] = SECUREC_CHAR('0'); 957 prefix[1] = (SecChar)(digits[16]); /* 16 for 'x' or 'X' */ 958 959#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) 960 if (ch == 'p') { 961 prefix[1] = SECUREC_CHAR('x'); 962 } 963#endif 964#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 965 if (ch == 'p') { 966 prefixLen = 0; 967 } else { 968 prefixLen = SECUREC_PREFIX_LEN; 969 } 970#else 971 prefixLen = SECUREC_PREFIX_LEN; 972#endif 973 974 } 975 /* fall-through */ /* FALLTHRU */ 976 case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ 977 case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ 978 case SECUREC_CHAR('u'): /* fall-through */ /* FALLTHRU */ 979 case SECUREC_CHAR('o'): /* fall-through */ /* FALLTHRU */ 980 switch (ch) { 981 case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ 982 case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ 983 /* signed decimal output */ 984 formatAttr.flags |= SECUREC_FLAG_SIGNED; 985 /* fall-through */ /* FALLTHRU */ 986 case SECUREC_CHAR('u'): 987 radix = SECUREC_RADIX_DECIMAL; 988 break; 989 case SECUREC_CHAR('o'): 990 /* unsigned octal output */ 991 radix = SECUREC_RADIX_OCTAL; 992 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { 993 /* alternate form means force a leading 0 */ 994 formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL; 995 } 996 break; 997 default: 998 break; 999 } 1000 1001 do { 1002 1003 SecUnsignedInt64 number = 0; /* number to convert */ 1004 SecInt64 l; /* temp long value */ 1005 1006 /* read argument into variable l */ 1007 if (formatAttr.flags & SECUREC_FLAG_I64) { 1008 l = (SecInt64)va_arg(argList, SecInt64); 1009 } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) { 1010 l = (SecInt64)va_arg(argList, SecInt64); 1011 } else 1012#ifdef SECUREC_ON_64BITS 1013 if (formatAttr.flags & SECUREC_FLAG_LONG) { 1014 l = (long)va_arg(argList, long); 1015 } else 1016#endif /* SECUREC_ON_64BITS */ 1017 if (formatAttr.flags & SECUREC_FLAG_CHAR) { 1018 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 1019 l = (char)va_arg(argList, int); /* sign extend */ 1020 if (l >= 128) { /* 128 on some platform, char is always unsigned */ 1021 SecUnsignedInt64 tmpL = (SecUnsignedInt64)l; 1022 unsigned char tmpCh = (unsigned char)(~(tmpL)); 1023 l = tmpCh + 1; 1024 formatAttr.flags |= SECUREC_FLAG_NEGATIVE; 1025 } 1026 } else { 1027 l = (unsigned char)va_arg(argList, int); /* zero-extend */ 1028 } 1029 1030 } else if (formatAttr.flags & SECUREC_FLAG_SHORT) { 1031 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 1032 l = (short)va_arg(argList, int); /* sign extend */ 1033 } else { 1034 l = (unsigned short)va_arg(argList, int); /* zero-extend */ 1035 } 1036 1037 } 1038#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 1039 else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) { 1040 l = (ptrdiff_t)va_arg(argList, ptrdiff_t); /* sign extend */ 1041 } else if (formatAttr.flags & SECUREC_FLAG_SIZE) { 1042 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 1043 /* No suitable macros were found to handle the branch */ 1044 if (SecIsSameSize(sizeof(size_t), sizeof(long))) { 1045 l = va_arg(argList, long); /* sign extend */ 1046 } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) { 1047 l = va_arg(argList, long long); /* sign extend */ 1048 } else { 1049 l = va_arg(argList, int); /* sign extend */ 1050 } 1051 } else { 1052 l = (SecInt64)(size_t)va_arg(argList, size_t); /* sign extend */ 1053 } 1054 } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) { 1055 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 1056 l = va_arg(argList, SecInt64); /* sign extend */ 1057 } else { 1058 /* sign extend */ 1059 l = (SecInt64)(SecUnsignedInt64)va_arg(argList, SecUnsignedInt64); 1060 } 1061 } 1062#endif 1063 else { 1064 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 1065 l = va_arg(argList, int); /* sign extend */ 1066 } else { 1067 l = (unsigned int)va_arg(argList, int); /* zero-extend */ 1068 } 1069 1070 } 1071 1072 /* check for negative; copy into number */ 1073 if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) { 1074 number = (SecUnsignedInt64)(-l); 1075 formatAttr.flags |= SECUREC_FLAG_NEGATIVE; 1076 } else { 1077 number = (SecUnsignedInt64)l; 1078 } 1079 1080 if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) && 1081#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 1082 ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) && 1083#endif 1084#ifdef SECUREC_ON_64BITS 1085 ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) && 1086 ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) && 1087#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ 1088 ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) && 1089#endif 1090#endif 1091 ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) { 1092 1093 number &= 0xffffffff; /* use 0xffffffff as 32 bit mask */ 1094 } 1095 1096 /* check precision value for default */ 1097 if (formatAttr.precision < 0) { 1098 formatAttr.precision = 1; /* default precision */ 1099 } else { 1100#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1101 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1102#else 1103 if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) { 1104 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1105 } 1106#endif 1107 if (formatAttr.precision > SECUREC_MAX_PRECISION) { 1108 formatAttr.precision = SECUREC_MAX_PRECISION; 1109 } 1110 } 1111 1112 /* Check if data is 0; if so, turn off hex prefix, 1113 * 'p' add 0x prefix, otherwise not add prefix 1114 */ 1115 if (number == 0) { 1116#if !(defined(SECUREC_VXWORKS_PLATFORM) || defined(__hpux)) 1117 prefixLen = 0; 1118#else 1119 if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE)) { 1120 prefixLen = SECUREC_PREFIX_LEN; 1121 } else { 1122 prefixLen = 0; 1123 } 1124#endif 1125 } 1126 1127 /* Convert data to ASCII */ 1128 formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE]; 1129 1130 if (number > 0) { 1131#ifdef SECUREC_ON_64BITS 1132 switch (radix) { 1133 /* the compiler will optimize each one */ 1134 case SECUREC_RADIX_DECIMAL: 1135 SECUREC_SPECIAL_QWORD_BASE10(number); 1136 break; 1137 case SECUREC_RADIX_HEX: 1138 SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX); 1139 break; 1140 case SECUREC_RADIX_OCTAL: 1141 SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL); 1142 break; 1143 default: 1144 break; 1145 } 1146#else /* for 32 bits system */ 1147 if (number <= 0xFFFFFFFFUL) { 1148 /* in most case, the value to be converted is small value */ 1149 SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; 1150 switch (radix) { 1151 case SECUREC_RADIX_HEX: 1152 SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_HEX); 1153 break; 1154 case SECUREC_RADIX_OCTAL: 1155 SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_OCTAL); 1156 break; 1157 1158#ifdef _AIX 1159 /* the compiler will optimize div 10 */ 1160 case SECUREC_RADIX_DECIMAL: 1161 SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_DECIMAL); 1162 break; 1163#else 1164 case SECUREC_RADIX_DECIMAL: 1165 do { 1166 /* fast div 10 */ 1167 SecUnsignedInt32 q; 1168 SecUnsignedInt32 r; 1169 do { 1170 *--formatBuf.str = digits[n32Tmp % SECUREC_RADIX_DECIMAL]; 1171 q = (n32Tmp >> 1) + (n32Tmp >> 2); /* fast div magic 2 */ 1172 q = q + (q >> 4); /* fast div magic 4 */ 1173 q = q + (q >> 8); /* fast div magic 8 */ 1174 q = q + (q >> 16); /* fast div magic 16 */ 1175 q = q >> 3; /* fast div magic 3 */ 1176 r = n32Tmp - SECUREC_MUL_TEN(q); 1177 n32Tmp = (r > 9) ? (q + 1) : q; /* fast div magic 9 */ 1178 } while (n32Tmp != 0); 1179 } SECUREC_WHILE_ZERO; 1180 break; 1181#endif 1182 default: 1183 break; 1184 } /* end switch */ 1185 } else { 1186 /* the value to be converted is greater than 4G */ 1187#if defined(SECUREC_VXWORKS_VERSION_5_4) 1188 do { 1189 SecUnsignedInt32 digit = 0; /* ascii value of digit */ 1190 SecUnsignedInt64 quotient = 0; 1191 if (SecU64Div32(number,(SecUnsignedInt32)radix, "ient, &digit) != 0) { 1192 noOutput = 1; 1193 break; 1194 } 1195 *--formatBuf.str = digits[digit]; 1196 number = quotient; 1197 } while (number != 0); 1198#else 1199 switch (radix) { 1200 /* the compiler will optimize div 10 */ 1201 case SECUREC_RADIX_DECIMAL: 1202 SECUREC_SPECIAL_QWORD_BASE10(number); 1203 break; 1204 case SECUREC_RADIX_OCTAL: 1205 SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL); 1206 break; 1207 case SECUREC_RADIX_HEX: 1208 SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX); 1209 break; 1210 default: 1211 break; 1212 } 1213#endif 1214 } 1215#endif 1216 1217 } 1218 /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */ 1219 textLen = (int)(size_t)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str); 1220 if (formatAttr.precision > textLen) { 1221 int ii; 1222 for (ii = 0; ii < formatAttr.precision - textLen; ++ii) { 1223 *--formatBuf.str = '0'; 1224 } 1225 textLen = formatAttr.precision; 1226 } 1227 1228 /* Force a leading zero if FORCEOCTAL flag set */ 1229 if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && 1230 (textLen == 0 || formatBuf.str[0] != '0')) { 1231 *--formatBuf.str = '0'; 1232 ++textLen; /* add a zero */ 1233 } 1234 } SECUREC_WHILE_ZERO; 1235 break; 1236 default: 1237 break; 1238 } 1239 1240 while (noOutput < 1) { 1241 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 1242 if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) { 1243 /* prefix is a '-' */ 1244 prefix[0] = SECUREC_CHAR('-'); 1245 prefixLen = 1; 1246 } else if (formatAttr.flags & SECUREC_FLAG_SIGN) { 1247 /* prefix is '+' */ 1248 prefix[0] = SECUREC_CHAR('+'); 1249 prefixLen = 1; 1250 } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) { 1251 /* prefix is ' ' */ 1252 prefix[0] = SECUREC_CHAR(' '); 1253 prefixLen = 1; 1254 } 1255 } 1256 1257#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX)) 1258 if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (textLen == 0)) { 1259 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1260 formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1]; 1261 *formatBuf.str-- = '\0'; 1262 *formatBuf.str-- = ')'; 1263 *formatBuf.str-- = 'l'; 1264 *formatBuf.str-- = 'i'; 1265 *formatBuf.str-- = 'n'; 1266 *formatBuf.str = '('; 1267 textLen = 5; /* length of (nil) is 5 */ 1268 } 1269#endif 1270 1271 /* calculate amount of padding */ 1272 padding = (formatAttr.fldWidth - textLen) - prefixLen; 1273 1274 /* put out the padding, prefix, and text, in the correct order */ 1275 1276 if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) { 1277 /* pad on left with blanks */ 1278 if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { 1279 /* char * cast to wchar * */ 1280 SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); 1281 } else { 1282 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); 1283 } 1284 } 1285 1286 /* write prefix */ 1287 if (prefixLen > 0) { 1288 SecChar *pPrefix = prefix; 1289 if (SECUREC_IS_REST_BUF_ENOUGH(stream, prefixLen)) { 1290 /* max prefix len is 2, use loop copy */ /* char * cast to wchar * in WCHAR version */ 1291 SECUREC_SAFE_WRITE_STR_OPT(pPrefix, prefixLen, stream, &charsOut); 1292 } else { 1293 SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut); 1294 } 1295 } 1296 1297 if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT) 1298 && padding > 0) { 1299 /* write leading zeros */ 1300 if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { 1301 /* char * cast to wchar * */ 1302 SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut); 1303 } else { 1304 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut); 1305 } 1306 } 1307 1308 /* write text */ 1309#ifndef SECUREC_FOR_WCHAR 1310 if (formatAttr.bufferIsWide != 0 && (textLen > 0)) { 1311#if SECUREC_HAVE_WCTOMB 1312 wchar_t *p = formatBuf.wStr; 1313 int count = textLen; 1314 while (count > 0) { 1315 char tmpBuf[SECUREC_MB_LEN + 1]; 1316 SECUREC_MASK_MSVC_CRT_WARNING 1317 int retVal = wctomb(tmpBuf, *p); 1318 SECUREC_END_MASK_MSVC_CRT_WARNING 1319 if (retVal <= 0) { 1320 charsOut = -1; 1321 break; 1322 } 1323 SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut); 1324 --count; 1325 ++p; 1326 } 1327#else 1328 charsOut = -1; 1329 break; 1330#endif 1331 } else { 1332 if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) { 1333 SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut); 1334 } else { 1335 SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut); 1336 } 1337 } 1338#else /* SECUREC_FOR_WCHAR */ 1339 if (formatAttr.bufferIsWide == 0 && textLen > 0) { 1340#if SECUREC_HAVE_MBTOWC 1341 int count = textLen; 1342 char *p = formatBuf.str; 1343 1344 while (count > 0) { 1345 wchar_t wChar = L'\0'; 1346 int retVal = mbtowc(&wChar, p, (size_t)MB_CUR_MAX); 1347 if (retVal <= 0) { 1348 charsOut = -1; 1349 break; 1350 } 1351 SecWriteCharW(wChar, stream, &charsOut); 1352 p += retVal; 1353 count -= retVal; 1354 } 1355#else 1356 charsOut = -1; 1357 break; 1358#endif 1359 } else { 1360 if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) { 1361 /* char * cast to wchar * */ 1362 SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); 1363 } else { 1364 SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut); 1365 } 1366 } 1367#endif /* SECUREC_FOR_WCHAR */ 1368 1369 if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) { 1370 /* pad on right with blanks */ 1371 if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { 1372 /* char * cast to wchar * */ 1373 SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); 1374 } else { 1375 SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); 1376 } 1377 } 1378 break; 1379 } 1380#if SECUREC_ENABLE_SPRINTF_FLOAT 1381 if (floatBuf != NULL) { 1382 SECUREC_FREE(floatBuf); 1383 floatBuf = NULL; 1384 } 1385#endif 1386 break; 1387 case STAT_INVALID: 1388 return -1; 1389 default: 1390 return -1; /* input format is wrong, directly return */ 1391 } 1392 } 1393 1394 if (state != STAT_NORMAL && state != STAT_TYPE) { 1395 return -1; 1396 } 1397 1398 return charsOut; /* the number of characters written */ 1399} 1400#endif /* OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */ 1401 1402