1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved. 3 * Licensed under Mulan PSL v2. 4 * You can use this software according to the terms and conditions of the Mulan PSL v2. 5 * You may obtain a copy of Mulan PSL v2 at: 6 * http://license.coscl.org.cn/MulanPSL2 7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 8 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 9 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 10 * See the Mulan PSL v2 for more details. 11 * Description: Used by secureprintoutput_a.c and secureprintoutput_w.c to include. 12 * This file provides a template function for ANSI and UNICODE compiling 13 * by different type definition. The functions of SecOutputS or 14 * SecOutputSW provides internal implementation for printf family API, such as sprintf, swprintf_s. 15 * Create: 2014-02-25 16 * Notes: see www.cplusplus.com/reference/cstdio/printf/ 17 */ 18/* 19 * [Standardize-exceptions] Use unsafe function: Portability 20 * [reason] Use unsafe function to implement security function to maintain platform compatibility. 21 * And sufficient input validation is performed before calling 22 */ 23#ifndef OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 24#define OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 25 26#ifndef SECUREC_ENABLE_SPRINTF_LONG_DOUBLE 27/* Some compilers do not support long double */ 28#define SECUREC_ENABLE_SPRINTF_LONG_DOUBLE 1 29#endif 30 31#define SECUREC_NULL_STRING_SIZE 8 32#define SECUREC_STATE_TABLE_SIZE 337 33 34#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) 35#define SECUREC_DIV_QUOTIENT_OCTAL(val64) ((val64) >> 3ULL) 36#define SECUREC_DIV_RESIDUE_OCTAL(val64) ((val64) & 7ULL) 37 38#define SECUREC_DIV_QUOTIENT_HEX(val64) ((val64) >> 4ULL) 39#define SECUREC_DIV_RESIDUE_HEX(val64) ((val64) & 0xfULL) 40#endif 41 42#define SECUREC_RADIX_OCTAL 8U 43#define SECUREC_RADIX_DECIMAL 10U 44#define SECUREC_RADIX_HEX 16U 45#define SECUREC_PREFIX_LEN 2 46/* Size include '+' and '\0' */ 47#define SECUREC_FLOAT_BUF_EXT 2 48 49/* Sign extend or Zero-extend */ 50#define SECUREC_GET_LONG_FROM_ARG(attr) ((((attr).flags & SECUREC_FLAG_SIGNED) != 0) ? \ 51 (SecInt64)(long)va_arg(argList, long) : \ 52 (SecInt64)(unsigned long)va_arg(argList, long)) 53 54/* Sign extend or Zero-extend */ 55#define SECUREC_GET_CHAR_FROM_ARG(attr) ((((attr).flags & SECUREC_FLAG_SIGNED) != 0) ? \ 56 SecUpdateNegativeChar(&(attr), ((char)va_arg(argList, int))) : \ 57 (SecInt64)(unsigned char)va_arg(argList, int)) 58 59/* Sign extend or Zero-extend */ 60#define SECUREC_GET_SHORT_FROM_ARG(attr) ((((attr).flags & SECUREC_FLAG_SIGNED) != 0) ? \ 61 (SecInt64)(short)va_arg(argList, int) : \ 62 (SecInt64)(unsigned short)va_arg(argList, int)) 63 64/* Sign extend or Zero-extend */ 65#define SECUREC_GET_INT_FROM_ARG(attr) ((((attr).flags & SECUREC_FLAG_SIGNED) != 0) ? \ 66 (SecInt64)(int)va_arg(argList, int) : \ 67 (SecInt64)(unsigned int)va_arg(argList, int)) 68 69#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 70/* Sign extend or Zero-extend. No suitable macros were found to handle the branch */ 71#define SECUREC_GET_SIZE_FROM_ARG(attr) ((((attr).flags & SECUREC_FLAG_SIGNED) != 0) ? \ 72 ((SecIsSameSize(sizeof(size_t), sizeof(long)) != 0) ? (SecInt64)(long)va_arg(argList, long) : \ 73 ((SecIsSameSize(sizeof(size_t), sizeof(long long)) != 0) ? (SecInt64)(long long)va_arg(argList, long long) : \ 74 (SecInt64)(int)va_arg(argList, int))) : \ 75 (SecInt64)(size_t)va_arg(argList, size_t)) 76#endif 77 78/* Format output buffer pointer and available size */ 79typedef struct { 80 int count; 81 SecChar *cur; 82} SecPrintfStream; 83 84typedef union { 85 /* Integer formatting refers to the end of the buffer, plus 1 to prevent tool alarms */ 86 char str[SECUREC_BUFFER_SIZE + 1]; 87#if SECUREC_HAVE_WCHART 88 wchar_t wStr[SECUREC_WCHAR_BUFFER_SIZE]; /* Just for %lc */ 89#endif 90} SecBuffer; 91 92typedef union { 93 char *str; /* Not a null terminated string */ 94#if SECUREC_HAVE_WCHART 95 wchar_t *wStr; 96#endif 97} SecFormatBuf; 98 99typedef struct { 100 const char *digits; /* Point to the hexadecimal subset */ 101 SecFormatBuf text; /* Point to formatted string */ 102 int textLen; /* Length of the text */ 103 int textIsWide; /* Flag for text is wide chars ; 0 is not wide char */ 104 unsigned int radix; /* Use for output number , default set to 10 */ 105 unsigned int flags; 106 int fldWidth; 107 int precision; 108 int dynWidth; /* %* 1 width from variable parameter ;0 not */ 109 int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ 110 int padding; /* Padding len */ 111 int prefixLen; /* Length of prefix, 0 or 1 or 2 */ 112 SecChar prefix[SECUREC_PREFIX_LEN]; /* Prefix is 0 or 0x */ 113 SecBuffer buffer; 114} SecFormatAttr; 115 116#if SECUREC_ENABLE_SPRINTF_FLOAT 117#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K 118#define SECUREC_FMT_STR_LEN 8 119#else 120#define SECUREC_FMT_STR_LEN 16 121#endif 122typedef struct { 123 char buffer[SECUREC_FMT_STR_LEN]; 124 char *fmtStr; /* Initialization must point to buffer */ 125 char *allocatedFmtStr; /* Initialization must be NULL to store allocated point */ 126 char *floatBuffer; /* Use heap memory if the SecFormatAttr.buffer is not enough */ 127 int bufferSize; /* The size of floatBuffer */ 128} SecFloatAdapt; 129#endif 130 131/* Use 20 to Align the data */ 132#define SECUREC_DIGITS_BUF_SIZE 20 133/* The serial number of 'x' or 'X' is 16 */ 134#define SECUREC_NUMBER_OF_X 16 135/* Some systems can not use pointers to point to string literals, but can use string arrays. */ 136/* For example, when handling code under uboot, there is a problem with the pointer */ 137static const char g_itoaUpperDigits[SECUREC_DIGITS_BUF_SIZE] = "0123456789ABCDEFX"; 138static const char g_itoaLowerDigits[SECUREC_DIGITS_BUF_SIZE] = "0123456789abcdefx"; 139 140#if SECUREC_ENABLE_SPRINTF_FLOAT 141/* Call system sprintf to format float value */ 142SECUREC_INLINE int SecFormatFloat(char *strDest, const char *format, ...) 143{ 144 int ret; /* If initialization causes e838 */ 145 va_list argList; 146 147 va_start(argList, format); 148 SECUREC_MASK_VSPRINTF_WARNING 149 ret = vsprintf(strDest, format, argList); 150 SECUREC_END_MASK_VSPRINTF_WARNING 151 va_end(argList); 152 (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 153 154 return ret; 155} 156 157#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && SECUREC_ENABLE_SPRINTF_LONG_DOUBLE 158/* Out put long double value to dest */ 159SECUREC_INLINE void SecFormatLongDouble(SecFormatAttr *attr, const SecFloatAdapt *floatAdapt, long double ldValue) 160{ 161 int fldWidth = (((attr->flags & SECUREC_FLAG_LEFT) != 0) ? (-attr->fldWidth) : attr->fldWidth); 162 if (attr->dynWidth != 0 && attr->dynPrecision != 0) { 163 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, attr->precision, ldValue); 164 } else if (attr->dynWidth != 0) { 165 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, ldValue); 166 } else if (attr->dynPrecision != 0) { 167 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, attr->precision, ldValue); 168 } else { 169 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, ldValue); 170 } 171 if (attr->textLen < 0 || attr->textLen >= floatAdapt->bufferSize) { 172 attr->textLen = 0; 173 } 174} 175#endif 176 177/* Out put double value to dest */ 178SECUREC_INLINE void SecFormatDouble(SecFormatAttr *attr, const SecFloatAdapt *floatAdapt, double dValue) 179{ 180 int fldWidth = (((attr->flags & SECUREC_FLAG_LEFT) != 0) ? (-attr->fldWidth) : attr->fldWidth); 181 if (attr->dynWidth != 0 && attr->dynPrecision != 0) { 182 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, attr->precision, dValue); 183 } else if (attr->dynWidth != 0) { 184 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, dValue); 185 } else if (attr->dynPrecision != 0) { 186 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, attr->precision, dValue); 187 } else { 188 attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, dValue); 189 } 190 if (attr->textLen < 0 || attr->textLen >= floatAdapt->bufferSize) { 191 attr->textLen = 0; 192 } 193} 194#endif 195 196#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 197/* To clear e506 warning */ 198SECUREC_INLINE int SecIsSameSize(size_t sizeA, size_t sizeB) 199{ 200 return (int)(sizeA == sizeB); 201} 202#endif 203 204#ifndef SECUREC_ON_64BITS 205/* 206 * Compiler Optimized Division 8. 207 * The text.str point to buffer end, must be Large enough 208 */ 209SECUREC_INLINE void SecNumber32ToOctalString(SecUnsignedInt32 number, SecFormatAttr *attr) 210{ 211 SecUnsignedInt32 val32 = number; 212 do { 213 --attr->text.str; 214 /* Just use lowerDigits for 0 - 9 */ 215 *(attr->text.str) = g_itoaLowerDigits[val32 % SECUREC_RADIX_OCTAL]; 216 val32 /= SECUREC_RADIX_OCTAL; 217 } while (val32 != 0); 218} 219 220#ifdef _AIX 221/* 222 * Compiler Optimized Division 10. 223 * The text.str point to buffer end, must be Large enough 224 */ 225SECUREC_INLINE void SecNumber32ToDecString(SecUnsignedInt32 number, SecFormatAttr *attr) 226{ 227 SecUnsignedInt32 val32 = number; 228 do { 229 --attr->text.str; 230 /* Just use lowerDigits for 0 - 9 */ 231 *(attr->text.str) = g_itoaLowerDigits[val32 % SECUREC_RADIX_DECIMAL]; 232 val32 /= SECUREC_RADIX_DECIMAL; 233 } while (val32 != 0); 234} 235#endif 236/* 237 * Compiler Optimized Division 16. 238 * The text.str point to buffer end, must be Large enough 239 */ 240SECUREC_INLINE void SecNumber32ToHexString(SecUnsignedInt32 number, SecFormatAttr *attr) 241{ 242 SecUnsignedInt32 val32 = number; 243 do { 244 --attr->text.str; 245 *(attr->text.str) = attr->digits[val32 % SECUREC_RADIX_HEX]; 246 val32 /= SECUREC_RADIX_HEX; 247 } while (val32 != 0); 248} 249 250#ifndef _AIX 251/* Use fast div 10 */ 252SECUREC_INLINE void SecNumber32ToDecStringFast(SecUnsignedInt32 number, SecFormatAttr *attr) 253{ 254 SecUnsignedInt32 val32 = number; 255 do { 256 SecUnsignedInt32 quotient; 257 SecUnsignedInt32 remain; 258 --attr->text.str; 259 *(attr->text.str) = g_itoaLowerDigits[val32 % SECUREC_RADIX_DECIMAL]; 260 quotient = (val32 >> 1U) + (val32 >> 2U); /* Fast div magic 2 */ 261 quotient = quotient + (quotient >> 4U); /* Fast div magic 4 */ 262 quotient = quotient + (quotient >> 8U); /* Fast div magic 8 */ 263 quotient = quotient + (quotient >> 16U); /* Fast div magic 16 */ 264 quotient = quotient >> 3U; /* Fast div magic 3 */ 265 remain = val32 - SECUREC_MUL_TEN(quotient); 266 val32 = (remain > 9U) ? (quotient + 1U) : quotient; /* Fast div magic 9 */ 267 } while (val32 != 0); 268} 269#endif 270 271SECUREC_INLINE void SecNumber32ToString(SecUnsignedInt32 number, SecFormatAttr *attr) 272{ 273 switch (attr->radix) { 274 case SECUREC_RADIX_HEX: 275 SecNumber32ToHexString(number, attr); 276 break; 277 case SECUREC_RADIX_OCTAL: 278 SecNumber32ToOctalString(number, attr); 279 break; 280 case SECUREC_RADIX_DECIMAL: 281#ifdef _AIX 282 /* The compiler will optimize div 10 */ 283 SecNumber32ToDecString(number, attr); 284#else 285 SecNumber32ToDecStringFast(number, attr); 286#endif 287 break; 288 default: 289 /* Do nothing */ 290 break; 291 } 292} 293#endif 294 295#if defined(SECUREC_USE_SPECIAL_DIV64) || (defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)) 296/* 297 * This function just to clear warning, on sume vxworks compiler shift 32 bit make warnings 298 */ 299SECUREC_INLINE SecUnsignedInt64 SecU64Shr32(SecUnsignedInt64 number) 300{ 301 return (((number) >> 16U) >> 16U); /* Two shifts of 16 bits to realize shifts of 32 bits */ 302} 303/* 304 * Fast divide by 10 algorithm. 305 * Calculation divisor multiply 0xcccccccccccccccdULL, resultHi64 >> 3 as quotient 306 */ 307SECUREC_INLINE void SecU64Div10(SecUnsignedInt64 divisor, SecUnsignedInt64 *quotient, SecUnsignedInt32 *residue) 308{ 309 SecUnsignedInt64 mask = 0xffffffffULL; /* Use 0xffffffffULL as 32 bit mask */ 310 SecUnsignedInt64 magicHi = 0xccccccccULL; /* Fast divide 10 magic numbers high 32bit 0xccccccccULL */ 311 SecUnsignedInt64 magicLow = 0xcccccccdULL; /* Fast divide 10 magic numbers low 32bit 0xcccccccdULL */ 312 SecUnsignedInt64 divisorHi = (SecUnsignedInt64)(SecU64Shr32(divisor)); /* High 32 bit use */ 313 SecUnsignedInt64 divisorLow = (SecUnsignedInt64)(divisor & mask); /* Low 32 bit mask */ 314 SecUnsignedInt64 factorHi = divisorHi * magicHi; 315 SecUnsignedInt64 factorLow1 = divisorHi * magicLow; 316 SecUnsignedInt64 factorLow2 = divisorLow * magicHi; 317 SecUnsignedInt64 factorLow3 = divisorLow * magicLow; 318 SecUnsignedInt64 carry = (factorLow1 & mask) + (factorLow2 & mask) + SecU64Shr32(factorLow3); 319 SecUnsignedInt64 resultHi64 = factorHi + SecU64Shr32(factorLow1) + SecU64Shr32(factorLow2) + SecU64Shr32(carry); 320 321 *quotient = resultHi64 >> 3U; /* Fast divide 10 magic numbers 3 */ 322 *residue = (SecUnsignedInt32)(divisor - ((*quotient) * 10)); /* Quotient mul 10 */ 323 return; 324} 325#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) 326/* 327 * Divide function for VXWORKS 328 */ 329SECUREC_INLINE int SecU64Div32(SecUnsignedInt64 divisor, SecUnsignedInt32 radix, 330 SecUnsignedInt64 *quotient, SecUnsignedInt32 *residue) 331{ 332 switch (radix) { 333 case SECUREC_RADIX_DECIMAL: 334 SecU64Div10(divisor, quotient, residue); 335 break; 336 case SECUREC_RADIX_HEX: 337 *quotient = SECUREC_DIV_QUOTIENT_HEX(divisor); 338 *residue = (SecUnsignedInt32)SECUREC_DIV_RESIDUE_HEX(divisor); 339 break; 340 case SECUREC_RADIX_OCTAL: 341 *quotient = SECUREC_DIV_QUOTIENT_OCTAL(divisor); 342 *residue = (SecUnsignedInt32)SECUREC_DIV_RESIDUE_OCTAL(divisor); 343 break; 344 default: 345 return -1; /* This does not happen in the current file */ 346 } 347 return 0; 348} 349SECUREC_INLINE void SecNumber64ToStringSpecial(SecUnsignedInt64 number, SecFormatAttr *attr) 350{ 351 SecUnsignedInt64 val64 = number; 352 do { 353 SecUnsignedInt32 digit = 0; /* Ascii value of digit */ 354 SecUnsignedInt64 quotient = 0; 355 if (SecU64Div32(val64, (SecUnsignedInt32)attr->radix, "ient, &digit) != 0) { 356 /* Just break, when enter this function, no error is returned */ 357 break; 358 } 359 --attr->text.str; 360 *(attr->text.str) = attr->digits[digit]; 361 val64 = quotient; 362 } while (val64 != 0); 363} 364#endif 365#endif 366 367#if defined(SECUREC_ON_64BITS) || !defined(SECUREC_VXWORKS_VERSION_5_4) 368#if defined(SECUREC_USE_SPECIAL_DIV64) 369/* The compiler does not provide 64 bit division problems */ 370SECUREC_INLINE void SecNumber64ToDecString(SecUnsignedInt64 number, SecFormatAttr *attr) 371{ 372 SecUnsignedInt64 val64 = number; 373 do { 374 SecUnsignedInt64 quotient = 0; 375 SecUnsignedInt32 digit = 0; 376 SecU64Div10(val64, "ient, &digit); 377 --attr->text.str; 378 /* Just use lowerDigits for 0 - 9 */ 379 *(attr->text.str) = g_itoaLowerDigits[digit]; 380 val64 = quotient; 381 } while (val64 != 0); 382} 383#else 384/* 385 * Compiler Optimized Division 10. 386 * The text.str point to buffer end, must be Large enough 387 */ 388SECUREC_INLINE void SecNumber64ToDecString(SecUnsignedInt64 number, SecFormatAttr *attr) 389{ 390 SecUnsignedInt64 val64 = number; 391 do { 392 --attr->text.str; 393 /* Just use lowerDigits for 0 - 9 */ 394 *(attr->text.str) = g_itoaLowerDigits[val64 % SECUREC_RADIX_DECIMAL]; 395 val64 /= SECUREC_RADIX_DECIMAL; 396 } while (val64 != 0); 397} 398#endif 399 400/* 401 * Compiler Optimized Division 8. 402 * The text.str point to buffer end, must be Large enough 403 */ 404SECUREC_INLINE void SecNumber64ToOctalString(SecUnsignedInt64 number, SecFormatAttr *attr) 405{ 406 SecUnsignedInt64 val64 = number; 407 do { 408 --attr->text.str; 409 /* Just use lowerDigits for 0 - 9 */ 410 *(attr->text.str) = g_itoaLowerDigits[val64 % SECUREC_RADIX_OCTAL]; 411 val64 /= SECUREC_RADIX_OCTAL; 412 } while (val64 != 0); 413} 414/* 415 * Compiler Optimized Division 16. 416 * The text.str point to buffer end, must be Large enough 417 */ 418SECUREC_INLINE void SecNumber64ToHexString(SecUnsignedInt64 number, SecFormatAttr *attr) 419{ 420 SecUnsignedInt64 val64 = number; 421 do { 422 --attr->text.str; 423 *(attr->text.str) = attr->digits[val64 % SECUREC_RADIX_HEX]; 424 val64 /= SECUREC_RADIX_HEX; 425 } while (val64 != 0); 426} 427 428SECUREC_INLINE void SecNumber64ToString(SecUnsignedInt64 number, SecFormatAttr *attr) 429{ 430 switch (attr->radix) { 431 /* The compiler will optimize div 10 */ 432 case SECUREC_RADIX_DECIMAL: 433 SecNumber64ToDecString(number, attr); 434 break; 435 case SECUREC_RADIX_OCTAL: 436 SecNumber64ToOctalString(number, attr); 437 break; 438 case SECUREC_RADIX_HEX: 439 SecNumber64ToHexString(number, attr); 440 break; 441 default: 442 /* Do nothing */ 443 break; 444 } 445} 446#endif 447 448/* 449 * Converting integers to string 450 */ 451SECUREC_INLINE void SecNumberToString(SecUnsignedInt64 number, SecFormatAttr *attr) 452{ 453#ifdef SECUREC_ON_64BITS 454 SecNumber64ToString(number, attr); 455#else /* For 32 bits system */ 456 if (number <= 0xffffffffUL) { /* Use 0xffffffffUL to check if the value is in the 32-bit range */ 457 /* In most case, the value to be converted is small value */ 458 SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; 459 SecNumber32ToString(n32Tmp, attr); 460 } else { 461 /* The value to be converted is greater than 4G */ 462#if defined(SECUREC_VXWORKS_VERSION_5_4) 463 SecNumber64ToStringSpecial(number, attr); 464#else 465 SecNumber64ToString(number, attr); 466#endif 467 } 468#endif 469} 470 471SECUREC_INLINE int SecIsNumberNeedTo32Bit(const SecFormatAttr *attr) 472{ 473 return (int)(((attr->flags & SECUREC_FLAG_I64) == 0) && 474#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 475 ((attr->flags & SECUREC_FLAG_INTMAX) == 0) && 476#endif 477#ifdef SECUREC_ON_64BITS 478 ((attr->flags & SECUREC_FLAG_PTRDIFF) == 0) && 479 ((attr->flags & SECUREC_FLAG_SIZE) == 0) && 480#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ 481 ((attr->flags & SECUREC_FLAG_LONG) == 0) && 482#endif 483#endif 484 ((attr->flags & SECUREC_FLAG_LONGLONG) == 0)); 485} 486 487SECUREC_INLINE void SecNumberToBuffer(SecFormatAttr *attr, SecInt64 num64) 488{ 489 SecUnsignedInt64 number; 490 /* Check for negative; copy into number */ 491 if ((attr->flags & SECUREC_FLAG_SIGNED) != 0 && num64 < 0) { 492 number = (SecUnsignedInt64)(0 - (SecUnsignedInt64)num64); /* Wrap with unsigned int64 numbers */ 493 attr->flags |= SECUREC_FLAG_NEGATIVE; 494 } else { 495 number = (SecUnsignedInt64)num64; 496 } 497 if (SecIsNumberNeedTo32Bit(attr) != 0) { 498 number = (number & (SecUnsignedInt64)0xffffffffUL); /* Use 0xffffffff as 32 bit mask */ 499 } 500 501 /* The text.str must be point to buffer.str, this pointer is used outside the function */ 502 attr->text.str = &attr->buffer.str[SECUREC_BUFFER_SIZE]; 503 504 if (number == 0) { 505 /* Turn off hex prefix default, and textLen is zero */ 506 attr->prefixLen = 0; 507 attr->textLen = 0; 508 return; 509 } 510 511 /* Convert integer to string. It must be invoked when number > 0, otherwise the following logic is incorrect */ 512 SecNumberToString(number, attr); 513 /* Compute length of number, text.str must be in buffer.str */ 514 attr->textLen = (int)(size_t)((char *)&attr->buffer.str[SECUREC_BUFFER_SIZE] - attr->text.str); 515} 516 517/* 518 * Write one character to dest buffer 519 */ 520SECUREC_INLINE void SecWriteChar(SecPrintfStream *stream, SecChar ch, int *charsOut) 521{ 522 /* Count must be reduced first, In order to identify insufficient length */ 523 --stream->count; 524 if (stream->count >= 0) { 525 *(stream->cur) = ch; 526 ++stream->cur; 527 *charsOut = *charsOut + 1; 528 return; 529 } 530 /* No enough length */ 531 *charsOut = -1; 532} 533 534/* 535* Write multiple identical characters. 536*/ 537SECUREC_INLINE void SecWriteMultiChar(SecPrintfStream *stream, SecChar ch, int num, int *charsOut) 538{ 539 int count; 540 for (count = num; count > 0; --count) { 541 --stream->count; /* count may be negative,indicating insufficient space */ 542 if (stream->count < 0) { 543 *charsOut = -1; 544 return; 545 } 546 *(stream->cur) = ch; 547 ++stream->cur; 548 } 549 *charsOut = *charsOut + num; 550} 551 552/* 553* Write string function, where this function is called, make sure that len is greater than 0 554*/ 555SECUREC_INLINE void SecWriteString(SecPrintfStream *stream, const SecChar *str, int len, int *charsOut) 556{ 557 const SecChar *tmp = str; 558 int count; 559 for (count = len; count > 0; --count) { 560 --stream->count; /* count may be negative,indicating insufficient space */ 561 if (stream->count < 0) { 562 *charsOut = -1; 563 return; 564 } 565 *(stream->cur) = *tmp; 566 ++stream->cur; 567 ++tmp; 568 } 569 *charsOut = *charsOut + len; 570} 571 572/* Use loop copy char or wchar_t string */ 573SECUREC_INLINE void SecWriteStringByLoop(SecPrintfStream *stream, const SecChar *str, int len) 574{ 575 int i; 576 const SecChar *tmp = str; 577 for (i = 0; i < len; ++i) { 578 *stream->cur = *tmp; 579 ++stream->cur; 580 ++tmp; 581 } 582 stream->count -= len; 583} 584 585SECUREC_INLINE void SecWriteStringOpt(SecPrintfStream *stream, const SecChar *str, int len) 586{ 587 if (len < 12) { /* Performance optimization for mobile number length 12 */ 588 SecWriteStringByLoop(stream, str, len); 589 } else { 590 size_t count = (size_t)(unsigned int)len * sizeof(SecChar); 591 SECUREC_MEMCPY_WARP_OPT(stream->cur, str, count); 592 stream->cur += len; 593 stream->count -= len; 594 } 595} 596 597/* 598 * Return if buffer length is enough 599 * The count variable can be reduced to 0, and the external function complements the \0 terminator. 600 */ 601SECUREC_INLINE int SecIsStreamBufEnough(const SecPrintfStream *stream, int needLen) 602{ 603 return (int)(stream->count >= needLen); 604} 605 606/* Write text string */ 607SECUREC_INLINE void SecWriteTextOpt(SecPrintfStream *stream, const SecChar *str, int len, int *charsOut) 608{ 609 if (SecIsStreamBufEnough(stream, len) != 0) { 610 SecWriteStringOpt(stream, str, len); 611 *charsOut += len; 612 } else { 613 SecWriteString(stream, str, len, charsOut); 614 } 615} 616 617/* Write left padding */ 618SECUREC_INLINE void SecWriteLeftPadding(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 619{ 620 if ((attr->flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) == 0 && attr->padding > 0) { 621 /* Pad on left with blanks */ 622 SecWriteMultiChar(stream, SECUREC_CHAR(' '), attr->padding, charsOut); 623 } 624} 625 626/* Write prefix */ 627SECUREC_INLINE void SecWritePrefix(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 628{ 629 if (attr->prefixLen > 0) { 630 SecWriteString(stream, attr->prefix, attr->prefixLen, charsOut); 631 } 632} 633 634/* Write leading zeros */ 635SECUREC_INLINE void SecWriteLeadingZero(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 636{ 637 if ((attr->flags & SECUREC_FLAG_LEADZERO) != 0 && (attr->flags & SECUREC_FLAG_LEFT) == 0 && 638 attr->padding > 0) { 639 SecWriteMultiChar(stream, SECUREC_CHAR('0'), attr->padding, charsOut); 640 } 641} 642 643/* Write right padding */ 644SECUREC_INLINE void SecWriteRightPadding(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 645{ 646 if (*charsOut >= 0 && (attr->flags & SECUREC_FLAG_LEFT) != 0 && attr->padding > 0) { 647 /* Pad on right with blanks */ 648 SecWriteMultiChar(stream, SECUREC_CHAR(' '), attr->padding, charsOut); 649 } 650} 651 652#ifdef SECUREC_FOR_WCHAR 653#define SECUREC_TEXT_CHAR_PTR(text) ((text).wStr) 654#define SECUREC_NEED_CONVERT_TEXT(attr) ((attr)->textIsWide == 0) 655#if SECUREC_HAVE_MBTOWC 656#define SECUREC_WRITE_TEXT_AFTER_CONVERT(stream, attr, charsOut) SecWriteTextAfterMbtowc((stream), (attr), (charsOut)) 657#else 658#define SECUREC_WRITE_TEXT_AFTER_CONVERT(stream, attr, charsOut) (*(charsOut) = -1) 659#endif 660#else 661#define SECUREC_TEXT_CHAR_PTR(text) ((text).str) 662#define SECUREC_NEED_CONVERT_TEXT(attr) ((attr)->textIsWide != 0) 663#if SECUREC_HAVE_WCTOMB 664#define SECUREC_WRITE_TEXT_AFTER_CONVERT(stream, attr, charsOut) SecWriteTextAfterWctomb((stream), (attr), (charsOut)) 665#else 666#define SECUREC_WRITE_TEXT_AFTER_CONVERT(stream, attr, charsOut) (*(charsOut) = -1) 667#endif 668#endif 669 670#ifdef SECUREC_FOR_WCHAR 671#if SECUREC_HAVE_MBTOWC 672SECUREC_INLINE void SecWriteTextAfterMbtowc(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 673{ 674 const char *p = attr->text.str; 675 int count = attr->textLen; 676 while (count > 0) { 677 wchar_t wChar = L'\0'; 678 int retVal = mbtowc(&wChar, p, (size_t)MB_CUR_MAX); 679 if (retVal <= 0) { 680 *charsOut = -1; 681 break; 682 } 683 SecWriteChar(stream, wChar, charsOut); 684 if (*charsOut == -1) { 685 break; 686 } 687 p += retVal; 688 count -= retVal; 689 } 690} 691#endif 692#else /* Not SECUREC_FOR_WCHAR */ 693#if SECUREC_HAVE_WCTOMB 694SECUREC_INLINE void SecWriteTextAfterWctomb(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 695{ 696 const wchar_t *p = attr->text.wStr; 697 int count = attr->textLen; 698 while (count > 0) { 699 char tmpBuf[SECUREC_MB_LEN + 1]; 700 SECUREC_MASK_MSVC_CRT_WARNING 701 int retVal = wctomb(tmpBuf, *p); 702 SECUREC_END_MASK_MSVC_CRT_WARNING 703 if (retVal <= 0) { 704 *charsOut = -1; 705 break; 706 } 707 SecWriteString(stream, tmpBuf, retVal, charsOut); 708 if (*charsOut == -1) { 709 break; 710 } 711 --count; 712 ++p; 713 } 714} 715#endif 716#endif 717 718#if SECUREC_ENABLE_SPRINTF_FLOAT 719/* 720 * Write text of float 721 * Using independent functions to optimize the expansion of inline functions by the compiler 722 */ 723SECUREC_INLINE void SecWriteFloatText(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 724{ 725#ifdef SECUREC_FOR_WCHAR 726#if SECUREC_HAVE_MBTOWC 727 SecWriteTextAfterMbtowc(stream, attr, charsOut); 728#else 729 *charsOut = -1; 730 (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 731 (void)attr; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 732#endif 733#else /* Not SECUREC_FOR_WCHAR */ 734 SecWriteString(stream, attr->text.str, attr->textLen, charsOut); 735#endif 736} 737#endif 738 739/* Write text of integer or string ... */ 740SECUREC_INLINE void SecWriteText(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) 741{ 742 if (SECUREC_NEED_CONVERT_TEXT(attr)) { 743 SECUREC_WRITE_TEXT_AFTER_CONVERT(stream, attr, charsOut); 744 } else { 745 SecWriteTextOpt(stream, SECUREC_TEXT_CHAR_PTR(attr->text), attr->textLen, charsOut); 746 } 747} 748 749#define SECUREC_FMT_STATE_OFFSET 256 750 751SECUREC_INLINE SecFmtState SecDecodeState(SecChar ch, SecFmtState lastState) 752{ 753 static const unsigned char stateTable[SECUREC_STATE_TABLE_SIZE] = { 754 /* 755 * Type 756 * 0: nospecial meaning; 757 * 1: '%' 758 * 2: '.' 759 * 3: '*' 760 * 4: '0' 761 * 5: '1' ... '9' 762 * 6: ' ', '+', '-', '#' 763 * 7: 'h', 'l', 'L', 'w' , 'N', 'z', 'q', 't', 'j' 764 * 8: 'd', 'o', 'u', 'i', 'x', 'X', 'e', 'f', 'g', 'E', 'F', 'G', 's', 'c', '[', 'p' 765 */ 766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 768 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, 769 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 770 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 771 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 772 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, 773 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 774 /* Fill zero for normal char 128 byte for 0x80 - 0xff */ 775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 783 /* 784 * State 785 * 0: normal 786 * 1: percent 787 * 2: flag 788 * 3: width 789 * 4: dot 790 * 5: precis 791 * 6: size 792 * 7: type 793 * 8: invalid 794 */ 795 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 796 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, 797 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 798 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 799 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 800 0x00 801 }; 802 803#ifdef SECUREC_FOR_WCHAR 804 /* Convert to unsigned char to clear gcc 4.3.4 warning */ 805 unsigned char fmtType = (unsigned char)((((unsigned int)(int)(ch)) <= (unsigned int)(int)(L'~')) ? \ 806 (stateTable[(unsigned char)(ch)]) : 0); 807 return (SecFmtState)(stateTable[fmtType * ((unsigned char)STAT_INVALID + 1) + 808 (unsigned char)(lastState) + SECUREC_FMT_STATE_OFFSET]); 809#else 810 unsigned char fmtType = stateTable[(unsigned char)(ch)]; 811 return (SecFmtState)(stateTable[fmtType * ((unsigned char)STAT_INVALID + 1) + 812 (unsigned char)(lastState) + SECUREC_FMT_STATE_OFFSET]); 813#endif 814} 815 816SECUREC_INLINE void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) 817{ 818 switch (ch) { 819 case SECUREC_CHAR(' '): 820 attr->flags |= SECUREC_FLAG_SIGN_SPACE; 821 break; 822 case SECUREC_CHAR('+'): 823 attr->flags |= SECUREC_FLAG_SIGN; 824 break; 825 case SECUREC_CHAR('-'): 826 attr->flags |= SECUREC_FLAG_LEFT; 827 break; 828 case SECUREC_CHAR('0'): 829 attr->flags |= SECUREC_FLAG_LEADZERO; /* Add zero th the front */ 830 break; 831 case SECUREC_CHAR('#'): 832 attr->flags |= SECUREC_FLAG_ALTERNATE; /* Output %x with 0x */ 833 break; 834 default: 835 /* Do nothing */ 836 break; 837 } 838 return; 839} 840 841/* 842 * Decoded size identifier in format string to Reduce the number of lines of function code 843 */ 844SECUREC_INLINE int SecDecodeSizeI(SecFormatAttr *attr, const SecChar **format) 845{ 846#ifdef SECUREC_ON_64BITS 847 attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */ 848#endif 849 if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) { 850 (*format) += 2; /* Add 2 to skip I64 */ 851 attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */ 852 } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) { 853 (*format) += 2; /* Add 2 to skip I32 */ 854 attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */ 855 } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) || 856 (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || 857 (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) { 858 /* Do nothing */ 859 } else { 860 /* Compatibility code for "%I" just print I */ 861 return -1; 862 } 863 return 0; 864} 865 866/* 867 * Decoded size identifier in format string, and skip format to next charater 868 */ 869SECUREC_INLINE int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) 870{ 871 switch (ch) { 872 case SECUREC_CHAR('l'): 873 if (**format == SECUREC_CHAR('l')) { 874 *format = *format + 1; 875 attr->flags |= SECUREC_FLAG_LONGLONG; /* For long long */ 876 } else { 877 attr->flags |= SECUREC_FLAG_LONG; /* For long int or wchar_t */ 878 } 879 break; 880#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 881 case SECUREC_CHAR('z'): /* fall-through */ /* FALLTHRU */ 882 case SECUREC_CHAR('Z'): 883 attr->flags |= SECUREC_FLAG_SIZE; 884 break; 885 case SECUREC_CHAR('j'): 886 attr->flags |= SECUREC_FLAG_INTMAX; 887 break; 888#endif 889 case SECUREC_CHAR('t'): 890 attr->flags |= SECUREC_FLAG_PTRDIFF; 891 break; 892 case SECUREC_CHAR('q'): /* fall-through */ /* FALLTHRU */ 893 case SECUREC_CHAR('L'): 894 attr->flags |= (SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE); 895 break; 896 case SECUREC_CHAR('I'): 897 if (SecDecodeSizeI(attr, format) != 0) { 898 /* Compatibility code for "%I" just print I */ 899 return -1; 900 } 901 break; 902 case SECUREC_CHAR('h'): 903 if (**format == SECUREC_CHAR('h')) { 904 *format = *format + 1; 905 attr->flags |= SECUREC_FLAG_CHAR; /* For char */ 906 } else { 907 attr->flags |= SECUREC_FLAG_SHORT; /* For short int */ 908 } 909 break; 910 case SECUREC_CHAR('w'): 911 attr->flags |= SECUREC_FLAG_WIDECHAR; /* For wide char */ 912 break; 913 default: 914 /* Do nothing */ 915 break; 916 } 917 return 0; 918} 919 920/* 921 * Decoded char type identifier 922 */ 923SECUREC_INLINE void SecDecodeTypeC(SecFormatAttr *attr, unsigned int c) 924{ 925 attr->textLen = 1; /* Only 1 wide character */ 926 927#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS)) 928 attr->flags &= ~SECUREC_FLAG_LEADZERO; 929#endif 930 931#ifdef SECUREC_FOR_WCHAR 932 if ((attr->flags & SECUREC_FLAG_SHORT) != 0) { 933 /* Get multibyte character from argument */ 934 attr->buffer.str[0] = (char)c; 935 attr->text.str = attr->buffer.str; 936 attr->textIsWide = 0; 937 } else { 938 attr->buffer.wStr[0] = (wchar_t)c; 939 attr->text.wStr = attr->buffer.wStr; 940 attr->textIsWide = 1; 941 } 942#else /* Not SECUREC_FOR_WCHAR */ 943 if ((attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) != 0) { 944#if SECUREC_HAVE_WCHART 945 attr->buffer.wStr[0] = (wchar_t)c; 946 attr->text.wStr = attr->buffer.wStr; 947 attr->textIsWide = 1; 948#else 949 attr->textLen = 0; /* Ignore unsupported characters */ 950 attr->fldWidth = 0; /* No paddings */ 951#endif 952 } else { 953 /* Get multibyte character from argument */ 954 attr->buffer.str[0] = (char)c; 955 attr->text.str = attr->buffer.str; 956 attr->textIsWide = 0; 957 } 958#endif 959} 960 961#ifdef SECUREC_FOR_WCHAR 962#define SECUREC_IS_NARROW_STRING(attr) (((attr)->flags & SECUREC_FLAG_SHORT) != 0) 963#else 964#define SECUREC_IS_NARROW_STRING(attr) (((attr)->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) == 0) 965#endif 966 967SECUREC_INLINE void SecDecodeTypeSchar(SecFormatAttr *attr) 968{ 969 size_t textLen; 970 if (attr->text.str == NULL) { 971 /* 972 * Literal string to print null ptr, define it as array rather than const text area 973 * To avoid gcc warning with pointing const text with variable 974 */ 975 static char strNullString[SECUREC_NULL_STRING_SIZE] = "(null)"; 976 attr->text.str = strNullString; 977 } 978 if (attr->precision == -1) { 979 /* Precision NOT assigned */ 980 /* The strlen performance is high when the string length is greater than 32 */ 981 textLen = strlen(attr->text.str); 982 if (textLen > SECUREC_STRING_MAX_LEN) { 983 textLen = 0; 984 } 985 } else { 986 /* Precision assigned */ 987 SECUREC_CALC_STR_LEN(attr->text.str, (size_t)(unsigned int)attr->precision, &textLen); 988 } 989 attr->textLen = (int)textLen; 990} 991 992SECUREC_INLINE void SecDecodeTypeSwchar(SecFormatAttr *attr) 993{ 994#if SECUREC_HAVE_WCHART 995 size_t textLen; 996 attr->textIsWide = 1; 997 if (attr->text.wStr == NULL) { 998 /* 999 * Literal string to print null ptr, define it as array rather than const text area 1000 * To avoid gcc warning with pointing const text with variable 1001 */ 1002 static wchar_t wStrNullString[SECUREC_NULL_STRING_SIZE] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; 1003 attr->text.wStr = wStrNullString; 1004 } 1005 /* The textLen in wchar_t,when precision is -1, it is unlimited */ 1006 SECUREC_CALC_WSTR_LEN(attr->text.wStr, (size_t)(unsigned int)attr->precision, &textLen); 1007 if (textLen > SECUREC_WCHAR_STRING_MAX_LEN) { 1008 textLen = 0; 1009 } 1010 attr->textLen = (int)textLen; 1011#else 1012 attr->textLen = 0; 1013#endif 1014} 1015 1016/* 1017 * Decoded string identifier 1018 */ 1019SECUREC_INLINE void SecDecodeTypeS(SecFormatAttr *attr, char *argPtr) 1020{ 1021#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) 1022#if (!defined(SECUREC_ON_UNIX)) 1023 attr->flags &= ~SECUREC_FLAG_LEADZERO; 1024#endif 1025#if (defined(SECUREC_FOR_WCHAR)) 1026 if ((attr->flags & SECUREC_FLAG_LONG) == 0) { 1027 attr->flags |= SECUREC_FLAG_SHORT; 1028 } 1029#endif 1030#endif 1031 attr->text.str = argPtr; 1032 if (SECUREC_IS_NARROW_STRING(attr)) { 1033 /* The textLen now contains length in multibyte chars */ 1034 SecDecodeTypeSchar(attr); 1035 } else { 1036 /* The textLen now contains length in wide chars */ 1037 SecDecodeTypeSwchar(attr); 1038 } 1039} 1040 1041/* 1042 * Check precision in format 1043 */ 1044SECUREC_INLINE int SecDecodePrecision(SecChar ch, SecFormatAttr *attr) 1045{ 1046 if (attr->dynPrecision == 0) { 1047 /* Add digit to current precision */ 1048 if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(attr->precision)) { 1049 return -1; 1050 } 1051 attr->precision = (int)SECUREC_MUL_TEN((unsigned int)attr->precision) + 1052 (unsigned char)(ch - SECUREC_CHAR('0')); 1053 } else { 1054 if (attr->precision < 0) { 1055 attr->precision = -1; 1056 } 1057 if (attr->precision > SECUREC_MAX_WIDTH_LEN) { 1058 return -1; 1059 } 1060 } 1061 return 0; 1062} 1063 1064/* 1065 * Check width in format 1066 */ 1067SECUREC_INLINE int SecDecodeWidth(SecChar ch, SecFormatAttr *attr, SecFmtState lastState) 1068{ 1069 if (attr->dynWidth == 0) { 1070 if (lastState != STAT_WIDTH) { 1071 attr->fldWidth = 0; 1072 } 1073 if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(attr->fldWidth)) { 1074 return -1; 1075 } 1076 attr->fldWidth = (int)SECUREC_MUL_TEN((unsigned int)attr->fldWidth) + 1077 (unsigned char)(ch - SECUREC_CHAR('0')); 1078 } else { 1079 if (attr->fldWidth < 0) { 1080 attr->flags |= SECUREC_FLAG_LEFT; 1081 attr->fldWidth = (-attr->fldWidth); 1082 } 1083 if (attr->fldWidth > SECUREC_MAX_WIDTH_LEN) { 1084 return -1; 1085 } 1086 } 1087 return 0; 1088} 1089 1090/* 1091 * The sprintf_s function processes the wide character as a parameter for %C 1092 * The swprintf_s function processes the multiple character as a parameter for %C 1093 */ 1094SECUREC_INLINE void SecUpdateWcharFlags(SecFormatAttr *attr) 1095{ 1096 if ((attr->flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) == 0) { 1097#ifdef SECUREC_FOR_WCHAR 1098 attr->flags |= SECUREC_FLAG_SHORT; 1099#else 1100 attr->flags |= SECUREC_FLAG_WIDECHAR; 1101#endif 1102 } 1103} 1104/* 1105 * When encountering %S, current just same as %C 1106 */ 1107SECUREC_INLINE void SecUpdateWstringFlags(SecFormatAttr *attr) 1108{ 1109 SecUpdateWcharFlags(attr); 1110} 1111 1112#if SECUREC_IN_KERNEL 1113SECUREC_INLINE void SecUpdatePointFlagsForKernel(SecFormatAttr *attr) 1114{ 1115 /* Width is not set */ 1116 if (attr->fldWidth <= 0) { 1117 attr->flags |= SECUREC_FLAG_LEADZERO; 1118 attr->fldWidth = 2 * sizeof(void *); /* 2 x byte number is the length of hex */ 1119 } 1120 if ((attr->flags & SECUREC_FLAG_ALTERNATE) != 0) { 1121 /* Alternate form means '0x' prefix */ 1122 attr->prefix[0] = SECUREC_CHAR('0'); 1123 attr->prefix[1] = SECUREC_CHAR('x'); 1124 attr->prefixLen = SECUREC_PREFIX_LEN; 1125 } 1126 attr->flags |= SECUREC_FLAG_LONG; /* Converting a long */ 1127} 1128#endif 1129 1130SECUREC_INLINE void SecUpdatePointFlags(SecFormatAttr *attr) 1131{ 1132 attr->flags |= SECUREC_FLAG_POINTER; 1133#if SECUREC_IN_KERNEL 1134 SecUpdatePointFlagsForKernel(attr); 1135#else 1136#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) 1137#if defined(SECUREC_VXWORKS_PLATFORM) 1138 attr->precision = 1; 1139#else 1140 attr->precision = 0; 1141#endif 1142 attr->flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ 1143 attr->digits = g_itoaLowerDigits; 1144#else /* On unix or win */ 1145#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 1146 attr->precision = 1; 1147#else 1148 attr->precision = 2 * sizeof(void *); /* 2 x byte number is the length of hex */ 1149#endif 1150#if defined(SECUREC_ON_UNIX) 1151 attr->digits = g_itoaLowerDigits; 1152#else 1153 attr->digits = g_itoaUpperDigits; 1154#endif 1155#endif 1156 1157#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1158 attr->flags &= ~SECUREC_FLAG_LEADZERO; 1159#endif 1160 1161#ifdef SECUREC_ON_64BITS 1162 attr->flags |= SECUREC_FLAG_I64; /* Converting an int64 */ 1163#else 1164 attr->flags |= SECUREC_FLAG_LONG; /* Converting a long */ 1165#endif 1166 /* Set up for %#p on different system */ 1167 if ((attr->flags & SECUREC_FLAG_ALTERNATE) != 0) { 1168 /* Alternate form means '0x' prefix */ 1169 attr->prefix[0] = SECUREC_CHAR('0'); 1170#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) 1171 attr->prefix[1] = SECUREC_CHAR('x'); 1172#else 1173 attr->prefix[1] = (SecChar)(attr->digits[SECUREC_NUMBER_OF_X]); 1174#endif 1175#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 1176 attr->prefixLen = 0; 1177#else 1178 attr->prefixLen = SECUREC_PREFIX_LEN; 1179#endif 1180 } 1181#endif 1182} 1183 1184SECUREC_INLINE void SecUpdateXpxFlags(SecFormatAttr *attr, SecChar ch) 1185{ 1186 /* Use unsigned lower hex output for 'x' */ 1187 attr->digits = g_itoaLowerDigits; 1188 attr->radix = SECUREC_RADIX_HEX; 1189 switch (ch) { 1190 case SECUREC_CHAR('p'): 1191 /* Print a pointer */ 1192 SecUpdatePointFlags(attr); 1193 break; 1194 case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ 1195 /* Unsigned upper hex output */ 1196 attr->digits = g_itoaUpperDigits; 1197 /* fall-through */ /* FALLTHRU */ 1198 default: 1199 /* For %#x or %#X */ 1200 if ((attr->flags & SECUREC_FLAG_ALTERNATE) != 0) { 1201 /* Alternate form means '0x' prefix */ 1202 attr->prefix[0] = SECUREC_CHAR('0'); 1203 attr->prefix[1] = (SecChar)(attr->digits[SECUREC_NUMBER_OF_X]); 1204 attr->prefixLen = SECUREC_PREFIX_LEN; 1205 } 1206 break; 1207 } 1208} 1209 1210SECUREC_INLINE void SecUpdateOudiFlags(SecFormatAttr *attr, SecChar ch) 1211{ 1212 /* Do not set digits here */ 1213 switch (ch) { 1214 case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ 1215 case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ 1216 /* For signed decimal output */ 1217 attr->flags |= SECUREC_FLAG_SIGNED; 1218 /* fall-through */ /* FALLTHRU */ 1219 case SECUREC_CHAR('u'): 1220 attr->radix = SECUREC_RADIX_DECIMAL; 1221 attr->digits = g_itoaLowerDigits; 1222 break; 1223 case SECUREC_CHAR('o'): 1224 /* For unsigned octal output */ 1225 attr->radix = SECUREC_RADIX_OCTAL; 1226 attr->digits = g_itoaLowerDigits; 1227 if ((attr->flags & SECUREC_FLAG_ALTERNATE) != 0) { 1228 /* Alternate form means force a leading 0 */ 1229 attr->flags |= SECUREC_FLAG_FORCE_OCTAL; 1230 } 1231 break; 1232 default: 1233 /* Do nothing */ 1234 break; 1235 } 1236} 1237 1238#if SECUREC_ENABLE_SPRINTF_FLOAT 1239SECUREC_INLINE void SecFreeFloatBuffer(SecFloatAdapt *floatAdapt) 1240{ 1241 if (floatAdapt->floatBuffer != NULL) { 1242 SECUREC_FREE(floatAdapt->floatBuffer); 1243 } 1244 if (floatAdapt->allocatedFmtStr != NULL) { 1245 SECUREC_FREE(floatAdapt->allocatedFmtStr); 1246 } 1247 floatAdapt->floatBuffer = NULL; 1248 floatAdapt->allocatedFmtStr = NULL; 1249 floatAdapt->fmtStr = NULL; 1250 floatAdapt->bufferSize = 0; 1251} 1252 1253SECUREC_INLINE void SecSeekToFrontPercent(const SecChar **format) 1254{ 1255 const SecChar *fmt = *format; 1256 while (*fmt != SECUREC_CHAR('%')) { /* Must meet '%' */ 1257 --fmt; 1258 } 1259 *format = fmt; 1260} 1261 1262/* Init float format, return 0 is OK */ 1263SECUREC_INLINE int SecInitFloatFmt(SecFloatAdapt *floatFmt, const SecChar *format) 1264{ 1265 const SecChar *fmt = format - 2; /* Sub 2 to the position before 'f' or 'g' */ 1266 int fmtStrLen; 1267 int i; 1268 1269 SecSeekToFrontPercent(&fmt); 1270 /* Now fmt point to '%' */ 1271 fmtStrLen = (int)(size_t)(format - fmt) + 1; /* With ending terminator */ 1272 if (fmtStrLen > (int)sizeof(floatFmt->buffer)) { 1273 /* When buffer is NOT enough, alloc a new buffer */ 1274 floatFmt->allocatedFmtStr = (char *)SECUREC_MALLOC((size_t)((unsigned int)fmtStrLen)); 1275 if (floatFmt->allocatedFmtStr == NULL) { 1276 return -1; 1277 } 1278 floatFmt->fmtStr = floatFmt->allocatedFmtStr; 1279 } else { 1280 floatFmt->fmtStr = floatFmt->buffer; 1281 floatFmt->allocatedFmtStr = NULL; /* Must set to NULL, later code free memory based on this identity */ 1282 } 1283 1284 for (i = 0; i < fmtStrLen - 1; ++i) { 1285 /* Convert wchar to char */ 1286 floatFmt->fmtStr[i] = (char)(fmt[i]); /* Copy the format string */ 1287 } 1288 floatFmt->fmtStr[fmtStrLen - 1] = '\0'; 1289 1290 return 0; 1291} 1292 1293/* Init float buffer and format, return 0 is OK */ 1294SECUREC_INLINE int SecInitFloatBuffer(SecFloatAdapt *floatAdapt, const SecChar *format, SecFormatAttr *attr) 1295{ 1296 floatAdapt->allocatedFmtStr = NULL; 1297 floatAdapt->fmtStr = NULL; 1298 floatAdapt->floatBuffer = NULL; 1299 /* Compute the precision value */ 1300 if (attr->precision < 0) { 1301 attr->precision = SECUREC_FLOAT_DEFAULT_PRECISION; 1302 } 1303 /* 1304 * Calc buffer size to store double value 1305 * The maximum length of SECUREC_MAX_WIDTH_LEN is enough 1306 */ 1307 if ((attr->flags & SECUREC_FLAG_LONG_DOUBLE) != 0) { 1308 if (attr->precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE_LB)) { 1309 return -1; 1310 } 1311 /* Long double needs to meet the basic print length */ 1312 floatAdapt->bufferSize = SECUREC_FLOAT_BUFSIZE_LB + attr->precision + SECUREC_FLOAT_BUF_EXT; 1313 } else { 1314 if (attr->precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE)) { 1315 return -1; 1316 } 1317 /* Double needs to meet the basic print length */ 1318 floatAdapt->bufferSize = SECUREC_FLOAT_BUFSIZE + attr->precision + SECUREC_FLOAT_BUF_EXT; 1319 } 1320 if (attr->fldWidth > floatAdapt->bufferSize) { 1321 floatAdapt->bufferSize = attr->fldWidth + SECUREC_FLOAT_BUF_EXT; 1322 } 1323 1324 if (floatAdapt->bufferSize > SECUREC_BUFFER_SIZE) { 1325 /* The current value of SECUREC_BUFFER_SIZE could not store the formatted float string */ 1326 floatAdapt->floatBuffer = (char *)SECUREC_MALLOC(((size_t)(unsigned int)floatAdapt->bufferSize)); 1327 if (floatAdapt->floatBuffer == NULL) { 1328 return -1; 1329 } 1330 attr->text.str = floatAdapt->floatBuffer; 1331 } else { 1332 attr->text.str = attr->buffer.str; /* Output buffer for float string with default size */ 1333 } 1334 1335 if (SecInitFloatFmt(floatAdapt, format) != 0) { 1336 if (floatAdapt->floatBuffer != NULL) { 1337 SECUREC_FREE(floatAdapt->floatBuffer); 1338 floatAdapt->floatBuffer = NULL; 1339 } 1340 return -1; 1341 } 1342 return 0; 1343} 1344#endif 1345 1346SECUREC_INLINE SecInt64 SecUpdateNegativeChar(SecFormatAttr *attr, char ch) 1347{ 1348 SecInt64 num64 = ch; /* Sign extend */ 1349 if (num64 >= 128) { /* 128 on some platform, char is always unsigned */ 1350 unsigned char tmp = (unsigned char)(~((unsigned char)ch)); 1351 num64 = tmp + 1; 1352 attr->flags |= SECUREC_FLAG_NEGATIVE; 1353 } 1354 return num64; 1355} 1356 1357/* 1358 * If the precision is not satisfied, zero is added before the string 1359 */ 1360SECUREC_INLINE void SecNumberSatisfyPrecision(SecFormatAttr *attr) 1361{ 1362 int precision; 1363 if (attr->precision < 0) { 1364 precision = 1; /* Default precision 1 */ 1365 } else { 1366#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1367 attr->flags &= ~SECUREC_FLAG_LEADZERO; 1368#else 1369 if ((attr->flags & SECUREC_FLAG_POINTER) == 0) { 1370 attr->flags &= ~SECUREC_FLAG_LEADZERO; 1371 } 1372#endif 1373 if (attr->precision > SECUREC_MAX_PRECISION) { 1374 attr->precision = SECUREC_MAX_PRECISION; 1375 } 1376 precision = attr->precision; 1377 } 1378 while (attr->textLen < precision) { 1379 --attr->text.str; 1380 *(attr->text.str) = '0'; 1381 ++attr->textLen; 1382 } 1383} 1384 1385/* 1386 * Add leading zero for %#o 1387 */ 1388SECUREC_INLINE void SecNumberForceOctal(SecFormatAttr *attr) 1389{ 1390 /* Force a leading zero if FORCEOCTAL flag set */ 1391 if ((attr->flags & SECUREC_FLAG_FORCE_OCTAL) != 0 && 1392 (attr->textLen == 0 || attr->text.str[0] != '0')) { 1393 --attr->text.str; 1394 *(attr->text.str) = '0'; 1395 ++attr->textLen; 1396 } 1397} 1398 1399SECUREC_INLINE void SecUpdateSignedNumberPrefix(SecFormatAttr *attr) 1400{ 1401 if ((attr->flags & SECUREC_FLAG_SIGNED) == 0) { 1402 return; 1403 } 1404 if ((attr->flags & SECUREC_FLAG_NEGATIVE) != 0) { 1405 /* Prefix is '-' */ 1406 attr->prefix[0] = SECUREC_CHAR('-'); 1407 attr->prefixLen = 1; 1408 return; 1409 } 1410 if ((attr->flags & SECUREC_FLAG_SIGN) != 0) { 1411 /* Prefix is '+' */ 1412 attr->prefix[0] = SECUREC_CHAR('+'); 1413 attr->prefixLen = 1; 1414 return; 1415 } 1416 if ((attr->flags & SECUREC_FLAG_SIGN_SPACE) != 0) { 1417 /* Prefix is ' ' */ 1418 attr->prefix[0] = SECUREC_CHAR(' '); 1419 attr->prefixLen = 1; 1420 return; 1421 } 1422 return; 1423} 1424 1425SECUREC_INLINE void SecNumberCompatZero(SecFormatAttr *attr) 1426{ 1427#if SECUREC_IN_KERNEL 1428 if ((attr->flags & SECUREC_FLAG_POINTER) != 0) { 1429 static char strNullPointer[SECUREC_NULL_STRING_SIZE] = "(null)"; 1430 attr->text.str = strNullPointer; 1431 attr->textLen = 6; /* Length of (null) is 6 */ 1432 attr->flags &= ~SECUREC_FLAG_LEADZERO; 1433 attr->prefixLen = 0; 1434 if (attr->precision >= 0 && attr->precision < attr->textLen) { 1435 attr->textLen = attr->precision; 1436 } 1437 } 1438 if ((attr->flags & SECUREC_FLAG_POINTER) == 0 && attr->radix == SECUREC_RADIX_HEX && 1439 (attr->flags & SECUREC_FLAG_ALTERNATE) != 0) { 1440 /* Add 0x prefix for %x or %X, the prefix string has been set before */ 1441 attr->prefixLen = SECUREC_PREFIX_LEN; 1442 } 1443#elif defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX)) 1444 if ((attr->flags & SECUREC_FLAG_POINTER) != 0) { 1445 static char strNullPointer[SECUREC_NULL_STRING_SIZE] = "(nil)"; 1446 attr->text.str = strNullPointer; 1447 attr->textLen = 5; /* Length of (nil) is 5 */ 1448 attr->flags &= ~SECUREC_FLAG_LEADZERO; 1449 } 1450#elif defined(SECUREC_VXWORKS_PLATFORM) || defined(__hpux) 1451 if ((attr->flags & SECUREC_FLAG_POINTER) != 0 && (attr->flags & SECUREC_FLAG_ALTERNATE) != 0) { 1452 /* Add 0x prefix for %p, the prefix string has been set before */ 1453 attr->prefixLen = SECUREC_PREFIX_LEN; 1454 } 1455#endif 1456 (void)attr; /* To clear e438 last value assigned not used , the compiler will optimize this code */ 1457} 1458 1459/* 1460 * Formatting output core function 1461 */ 1462SECUREC_INLINE int SecOutput(SecPrintfStream *stream, const SecChar *cFormat, va_list argList) 1463{ 1464 const SecChar *format = cFormat; 1465 int charsOut; /* Characters written */ 1466 int noOutput = 0; /* Must be initialized or compiler alerts */ 1467 SecFmtState state; 1468 SecFormatAttr formatAttr; 1469 1470 formatAttr.flags = 0; 1471 formatAttr.textIsWide = 0; /* Flag for buffer contains wide chars */ 1472 formatAttr.fldWidth = 0; 1473 formatAttr.precision = 0; 1474 formatAttr.dynWidth = 0; 1475 formatAttr.dynPrecision = 0; 1476 formatAttr.digits = g_itoaUpperDigits; 1477 formatAttr.radix = SECUREC_RADIX_DECIMAL; 1478 formatAttr.padding = 0; 1479 formatAttr.textLen = 0; 1480 formatAttr.text.str = NULL; 1481 formatAttr.prefixLen = 0; 1482 formatAttr.prefix[0] = SECUREC_CHAR('\0'); 1483 formatAttr.prefix[1] = SECUREC_CHAR('\0'); 1484 charsOut = 0; 1485 state = STAT_NORMAL; /* Starting state */ 1486 1487 /* Loop each format character */ 1488 while (*format != SECUREC_CHAR('\0') && charsOut >= 0) { 1489 SecFmtState lastState = state; 1490 SecChar ch = *format; /* Currently read character */ 1491 ++format; 1492 state = SecDecodeState(ch, lastState); 1493 switch (state) { 1494 case STAT_NORMAL: 1495 SecWriteChar(stream, ch, &charsOut); 1496 continue; 1497 case STAT_PERCENT: 1498 /* Set default values */ 1499 noOutput = 0; 1500 formatAttr.prefixLen = 0; 1501 formatAttr.textLen = 0; 1502 formatAttr.flags = 0; 1503 formatAttr.fldWidth = 0; 1504 formatAttr.precision = -1; 1505 formatAttr.textIsWide = 0; 1506 formatAttr.dynWidth = 0; 1507 formatAttr.dynPrecision = 0; 1508 break; 1509 case STAT_FLAG: 1510 /* Set flag based on which flag character */ 1511 SecDecodeFlags(ch, &formatAttr); 1512 break; 1513 case STAT_WIDTH: 1514 /* Update width value */ 1515 if (ch == SECUREC_CHAR('*')) { 1516 /* get width from arg list */ 1517 formatAttr.fldWidth = (int)va_arg(argList, int); 1518 formatAttr.dynWidth = 1; 1519 } 1520 if (SecDecodeWidth(ch, &formatAttr, lastState) != 0) { 1521 return -1; 1522 } 1523 break; 1524 case STAT_DOT: 1525 formatAttr.precision = 0; 1526 break; 1527 case STAT_PRECIS: 1528 /* Update precision value */ 1529 if (ch == SECUREC_CHAR('*')) { 1530 /* Get precision from arg list */ 1531 formatAttr.precision = (int)va_arg(argList, int); 1532 formatAttr.dynPrecision = 1; 1533 } 1534 if (SecDecodePrecision(ch, &formatAttr) != 0) { 1535 return -1; 1536 } 1537 break; 1538 case STAT_SIZE: 1539 /* Read a size specifier, set the formatAttr.flags based on it, and skip format to next character */ 1540 if (SecDecodeSize(ch, &formatAttr, &format) != 0) { 1541 /* Compatibility code for "%I" just print I */ 1542 SecWriteChar(stream, ch, &charsOut); 1543 state = STAT_NORMAL; 1544 continue; 1545 } 1546 break; 1547 case STAT_TYPE: 1548 switch (ch) { 1549 case SECUREC_CHAR('C'): /* Wide char */ 1550 SecUpdateWcharFlags(&formatAttr); 1551 /* fall-through */ /* FALLTHRU */ 1552 case SECUREC_CHAR('c'): { 1553 unsigned int cValue = (unsigned int)va_arg(argList, int); 1554 SecDecodeTypeC(&formatAttr, cValue); 1555 break; 1556 } 1557 case SECUREC_CHAR('S'): /* Wide char string */ 1558 SecUpdateWstringFlags(&formatAttr); 1559 /* fall-through */ /* FALLTHRU */ 1560 case SECUREC_CHAR('s'): { 1561 char *argPtr = (char *)va_arg(argList, char *); 1562 SecDecodeTypeS(&formatAttr, argPtr); 1563 break; 1564 } 1565 case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ 1566 case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ 1567 case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ 1568 case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ 1569 case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ 1570 case SECUREC_CHAR('f'): { 1571#if SECUREC_ENABLE_SPRINTF_FLOAT 1572 /* Add following code to call system sprintf API for float number */ 1573 SecFloatAdapt floatAdapt; 1574 noOutput = 1; /* It's no more data needs to be written */ 1575 1576 /* Now format is pointer to the next character of 'f' */ 1577 if (SecInitFloatBuffer(&floatAdapt, format, &formatAttr) != 0) { 1578 break; 1579 } 1580 1581 if ((formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) != 0) { 1582#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && SECUREC_ENABLE_SPRINTF_LONG_DOUBLE 1583 long double tmp = (long double)va_arg(argList, long double); 1584 SecFormatLongDouble(&formatAttr, &floatAdapt, tmp); 1585#else 1586 double tmp = (double)va_arg(argList, double); 1587 SecFormatDouble(&formatAttr, &floatAdapt, tmp); 1588#endif 1589 } else { 1590 double tmp = (double)va_arg(argList, double); 1591 SecFormatDouble(&formatAttr, &floatAdapt, tmp); 1592 } 1593 1594 /* Only need write formatted float string */ 1595 SecWriteFloatText(stream, &formatAttr, &charsOut); 1596 SecFreeFloatBuffer(&floatAdapt); 1597 break; 1598#else 1599 return -1; 1600#endif 1601 } 1602 case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ 1603 case SECUREC_CHAR('p'): /* fall-through */ /* FALLTHRU */ 1604 case SECUREC_CHAR('x'): /* fall-through */ /* FALLTHRU */ 1605 SecUpdateXpxFlags(&formatAttr, ch); 1606 /* fall-through */ /* FALLTHRU */ 1607 case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ 1608 case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ 1609 case SECUREC_CHAR('u'): /* fall-through */ /* FALLTHRU */ 1610 case SECUREC_CHAR('o'): { 1611 SecInt64 num64; 1612 SecUpdateOudiFlags(&formatAttr, ch); 1613 /* Read argument into variable num64. Be careful, depend on the order of judgment */ 1614 if ((formatAttr.flags & SECUREC_FLAG_I64) != 0 || 1615 (formatAttr.flags & SECUREC_FLAG_LONGLONG) != 0) { 1616 num64 = (SecInt64)va_arg(argList, SecInt64); /* Maximum Bit Width sign bit unchanged */ 1617 } else if ((formatAttr.flags & SECUREC_FLAG_LONG) != 0) { 1618 num64 = SECUREC_GET_LONG_FROM_ARG(formatAttr); 1619 } else if ((formatAttr.flags & SECUREC_FLAG_CHAR) != 0) { 1620 num64 = SECUREC_GET_CHAR_FROM_ARG(formatAttr); 1621 } else if ((formatAttr.flags & SECUREC_FLAG_SHORT) != 0) { 1622 num64 = SECUREC_GET_SHORT_FROM_ARG(formatAttr); 1623#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 1624 } else if ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) != 0) { 1625 num64 = (ptrdiff_t)va_arg(argList, ptrdiff_t); /* Sign extend */ 1626 } else if ((formatAttr.flags & SECUREC_FLAG_SIZE) != 0) { 1627 num64 = SECUREC_GET_SIZE_FROM_ARG(formatAttr); 1628 } else if ((formatAttr.flags & SECUREC_FLAG_INTMAX) != 0) { 1629 num64 = (SecInt64)va_arg(argList, SecInt64); 1630#endif 1631 } else { 1632 num64 = SECUREC_GET_INT_FROM_ARG(formatAttr); 1633 } 1634 1635 /* The order of the following calls must be correct */ 1636 SecNumberToBuffer(&formatAttr, num64); 1637 SecNumberSatisfyPrecision(&formatAttr); 1638 SecNumberForceOctal(&formatAttr); 1639 SecUpdateSignedNumberPrefix(&formatAttr); 1640 if (num64 == 0) { 1641 SecNumberCompatZero(&formatAttr); 1642 } 1643 break; 1644 } 1645 default: 1646 /* Do nothing */ 1647 break; 1648 } 1649 1650 if (noOutput == 0) { 1651 /* Calculate amount of padding */ 1652 formatAttr.padding = (formatAttr.fldWidth - formatAttr.textLen) - formatAttr.prefixLen; 1653 1654 /* Put out the padding, prefix, and text, in the correct order */ 1655 SecWriteLeftPadding(stream, &formatAttr, &charsOut); 1656 SecWritePrefix(stream, &formatAttr, &charsOut); 1657 SecWriteLeadingZero(stream, &formatAttr, &charsOut); 1658 SecWriteText(stream, &formatAttr, &charsOut); 1659 SecWriteRightPadding(stream, &formatAttr, &charsOut); 1660 } 1661 break; 1662 case STAT_INVALID: /* fall-through */ /* FALLTHRU */ 1663 default: 1664 return -1; /* Input format is wrong(STAT_INVALID), directly return */ 1665 } 1666 } 1667 1668 if (state != STAT_NORMAL && state != STAT_TYPE) { 1669 return -1; 1670 } 1671 1672 return charsOut; /* The number of characters written */ 1673} 1674 1675/* 1676 * Output one zero character zero into the SecPrintfStream structure 1677 * If there is not enough space, make sure f->count is less than 0 1678 */ 1679SECUREC_INLINE int SecPutZeroChar(SecPrintfStream *stream) 1680{ 1681 --stream->count; 1682 if (stream->count >= 0) { 1683 *(stream->cur) = SECUREC_CHAR('\0'); 1684 ++stream->cur; 1685 return 0; 1686 } 1687 return -1; 1688} 1689 1690/* 1691 * Multi character formatted output implementation 1692 */ 1693#ifdef SECUREC_FOR_WCHAR 1694int SecVswprintfImpl(wchar_t *string, size_t count, const wchar_t *format, va_list argList) 1695#else 1696int SecVsnprintfImpl(char *string, size_t count, const char *format, va_list argList) 1697#endif 1698{ 1699 SecPrintfStream stream; 1700 int retVal; 1701 1702 stream.count = (int)count; /* The count include \0 character, must be greater than zero */ 1703 stream.cur = string; 1704 1705 retVal = SecOutput(&stream, format, argList); 1706 if (retVal >= 0) { 1707 if (SecPutZeroChar(&stream) == 0) { 1708 return retVal; 1709 } 1710 } 1711 if (stream.count < 0) { 1712 /* The buffer was too small, then truncate */ 1713 string[count - 1] = SECUREC_CHAR('\0'); 1714 return SECUREC_PRINTF_TRUNCATE; 1715 } 1716 string[0] = SECUREC_CHAR('\0'); /* Empty the dest string */ 1717 return -1; 1718} 1719#endif /* OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */ 1720 1721