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