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