1#include <algorithm> 2#include <float.h> 3#include <math.h> 4#include <new> 5#include <stdlib.h> 6 7#include <GenericNumberFormat.h> 8#include <String.h> 9#include <UnicodeChar.h> 10 11#if __GNUC__ > 2 12using std::max; 13using std::min; 14using std::nothrow; 15#endif 16 17// constants (more below the helper classes) 18 19static const int kMaxIntDigitCount = 20; // int64: 19 + sign, uint64: 20 20static const int kMaxFloatDigitCount = DBL_DIG + 2; 21 // double: mantissa precision + 2 22 23 24// Symbol 25 26// constructor 27BGenericNumberFormat::Symbol::Symbol(const char *symbol) 28 : symbol(NULL), 29 length(0), 30 char_count(0) 31{ 32 SetTo(symbol); 33} 34 35// destructor 36BGenericNumberFormat::Symbol::~Symbol() 37{ 38 Unset(); 39} 40 41// SetTo 42status_t 43BGenericNumberFormat::Symbol::SetTo(const char *symbol) 44{ 45 // unset old 46 if (this->symbol) { 47 free(this->symbol); 48 length = 0; 49 char_count = 0; 50 } 51 // set new 52 if (symbol) { 53 this->symbol = strdup(symbol); 54 if (!this->symbol) 55 return B_NO_MEMORY; 56 length = strlen(this->symbol); 57 char_count = BUnicodeChar::UTF8StringLength(this->symbol); 58 } 59 return B_OK; 60} 61 62 63// SpecialNumberSymbols 64struct BGenericNumberFormat::SpecialNumberSymbols { 65 const Symbol *nan; 66 const Symbol *infinity; 67 const Symbol *negative_infinity; 68}; 69 70 71// GroupingInfo 72class BGenericNumberFormat::GroupingInfo { 73 public: 74 GroupingInfo() 75 : fSeparators(NULL), 76 fSeparatorCount(0), 77 fSizes(NULL), 78 fSizeCount(0), 79 fSumSizes(NULL), 80 fSumSeparators(NULL) 81 { 82 } 83 84 GroupingInfo(const char **separators, int32 separatorCount, 85 const size_t *sizes, int32 sizeCount) 86 : fSeparators(NULL), 87 fSeparatorCount(0), 88 fSizes(NULL), 89 fSizeCount(0), 90 fSumSizes(NULL), 91 fSumSeparators(NULL) 92 { 93 SetTo(separators, separatorCount, sizes, sizeCount); 94 } 95 96 ~GroupingInfo() 97 { 98 Unset(); 99 } 100 101 status_t SetTo(const char **separators, int32 separatorCount, 102 const size_t *sizes, int32 sizeCount) 103 { 104 // unset old 105 Unset(); 106 // set new 107 if ((!separators && separatorCount <= 0) 108 || (!sizes && sizeCount <= 0)) 109 return B_OK; 110 // allocate arrays 111 fSeparators = new(nothrow) Symbol[separatorCount]; 112 fSizes = new(nothrow) int32[sizeCount]; 113 fSumSizes = new(nothrow) int32[sizeCount]; 114 fSumSeparators = new(nothrow) Symbol*[separatorCount]; 115 if (!fSeparators || !fSizes || !fSumSizes || !fSumSeparators) { 116 Unset(); 117 return B_NO_MEMORY; 118 } 119 fSeparatorCount = separatorCount; 120 fSizeCount = sizeCount; 121 // separators 122 for (int i = 0; i < separatorCount; i++) { 123 status_t error = fSeparators[i].SetTo(separators[i]); 124 if (error != B_OK) { 125 Unset(); 126 return error; 127 } 128 } 129 // sizes and sum arrays 130 int32 sumSize = -1; 131 for (int32 i = 0; i < sizeCount; i++) { 132 fSizes[i] = (int32)sizes[i]; 133 sumSize += fSizes[i]; 134 fSumSizes[i] = sumSize; 135 fSumSeparators[i] = &fSeparators[min(i, fSeparatorCount)]; 136 } 137 return B_OK; 138 } 139 140 void Unset() 141 { 142 if (fSeparators) { 143 delete[] fSeparators; 144 fSeparators = NULL; 145 } 146 fSeparatorCount = 0; 147 if (fSizes) { 148 delete[] fSizes; 149 fSizes = NULL; 150 } 151 fSizeCount = 0; 152 if (fSumSizes) { 153 delete[] fSumSizes; 154 fSumSizes = NULL; 155 } 156 if (fSumSeparators) { 157 delete[] fSumSeparators; 158 fSumSeparators = NULL; 159 } 160 } 161 162 const Symbol *SeparatorForDigit(int32 position) const 163 { 164 for (int i = fSizeCount - 1; i >= 0; i--) { 165 if (fSumSizes[i] <= position) { 166 if (fSumSizes[i] == position 167 || (i == fSizeCount - 1 168 && (position - fSumSizes[i]) % fSizes[i] == 0)) { 169 return fSumSeparators[i]; 170 } 171 return NULL; 172 } 173 } 174 return NULL; 175 } 176 177 private: 178 Symbol *fSeparators; 179 int32 fSeparatorCount; 180 int32 *fSizes; 181 int32 fSizeCount; 182 int32 *fSumSizes; 183 Symbol **fSumSeparators; 184}; 185 186 187// SignSymbols 188class BGenericNumberFormat::SignSymbols { 189 public: 190 SignSymbols() 191 : fPlusPrefix(), 192 fMinusPrefix(), 193 fPadPlusPrefix(), 194 fNoForcePlusPrefix(), 195 fPlusSuffix(), 196 fMinusSuffix(), 197 fPadPlusSuffix(), 198 fNoForcePlusSuffix() 199 { 200 } 201 202 SignSymbols(const char *plusPrefix, const char *minusPrefix, 203 const char *padPlusPrefix, const char *noForcePlusPrefix, 204 const char *plusSuffix, const char *minusSuffix, 205 const char *padPlusSuffix, const char *noForcePlusSuffix) 206 : fPlusPrefix(plusPrefix), 207 fMinusPrefix(minusPrefix), 208 fPadPlusPrefix(padPlusPrefix), 209 fNoForcePlusPrefix(noForcePlusPrefix), 210 fPlusSuffix(plusSuffix), 211 fMinusSuffix(minusSuffix), 212 fPadPlusSuffix(padPlusSuffix), 213 fNoForcePlusSuffix(noForcePlusSuffix) 214 { 215 } 216 217 ~SignSymbols() 218 { 219 } 220 221 status_t SetTo(const char *plusPrefix, const char *minusPrefix, 222 const char *padPlusPrefix, const char *noForcePlusPrefix, 223 const char *plusSuffix, const char *minusSuffix, 224 const char *padPlusSuffix, const char *noForcePlusSuffix) 225 { 226 status_t error = B_OK; 227 if (error == B_OK) 228 error = fPlusPrefix.SetTo(plusPrefix); 229 if (error == B_OK) 230 error = fMinusPrefix.SetTo(minusPrefix); 231 if (error == B_OK) 232 error = fPadPlusPrefix.SetTo(noForcePlusPrefix); 233 if (error == B_OK) 234 error = fNoForcePlusPrefix.SetTo(noForcePlusPrefix); 235 if (error == B_OK) 236 error = fPlusSuffix.SetTo(plusSuffix); 237 if (error == B_OK) 238 error = fMinusSuffix.SetTo(minusSuffix); 239 if (error == B_OK) 240 error = fPadPlusSuffix.SetTo(noForcePlusSuffix); 241 if (error == B_OK) 242 error = fNoForcePlusSuffix.SetTo(noForcePlusSuffix); 243 if (error != B_OK) 244 Unset(); 245 return error; 246 } 247 248 void Unset() 249 { 250 fPlusPrefix.Unset(); 251 fMinusPrefix.Unset(); 252 fNoForcePlusPrefix.Unset(); 253 fPadPlusPrefix.Unset(); 254 fPlusSuffix.Unset(); 255 fMinusSuffix.Unset(); 256 fNoForcePlusSuffix.Unset(); 257 fPadPlusSuffix.Unset(); 258 } 259 260 const Symbol *PlusPrefix() const 261 { 262 return &fPlusPrefix; 263 } 264 265 const Symbol *MinusPrefix() const 266 { 267 return &fMinusPrefix; 268 } 269 270 const Symbol *PadPlusPrefix() const 271 { 272 return &fPadPlusPrefix; 273 } 274 275 const Symbol *NoForcePlusPrefix() const 276 { 277 return &fNoForcePlusPrefix; 278 } 279 280 const Symbol *PlusSuffix() const 281 { 282 return &fPlusSuffix; 283 } 284 285 const Symbol *MinusSuffix() const 286 { 287 return &fMinusSuffix; 288 } 289 290 const Symbol *PadPlusSuffix() const 291 { 292 return &fPadPlusSuffix; 293 } 294 295 const Symbol *NoForcePlusSuffix() const 296 { 297 return &fNoForcePlusSuffix; 298 } 299 300 private: 301 Symbol fPlusPrefix; 302 Symbol fMinusPrefix; 303 Symbol fPadPlusPrefix; 304 Symbol fNoForcePlusPrefix; 305 Symbol fPlusSuffix; 306 Symbol fMinusSuffix; 307 Symbol fPadPlusSuffix; 308 Symbol fNoForcePlusSuffix; 309}; 310 311 312// BufferWriter 313class BGenericNumberFormat::BufferWriter { 314 public: 315 BufferWriter(char *buffer = NULL, int32 bufferSize = 0) 316 { 317 SetTo(buffer, bufferSize); 318 } 319 320 void SetTo(char *buffer = NULL, int32 bufferSize = 0) 321 { 322 fBuffer = buffer; 323 fBufferSize = bufferSize; 324 fPosition = 0; 325 fCharCount = 0; 326 fDryRun = (!fBuffer || (fBufferSize == 0)); 327 if (!fDryRun) 328 fBuffer[0] = '\0'; 329 } 330 331 int32 StringLength() const 332 { 333 return fPosition; 334 } 335 336 int32 CharCount() const 337 { 338 return fCharCount; 339 } 340 341 bool IsOverflow() const 342 { 343 return (fPosition >= fBufferSize); 344 } 345 346 void Append(const char *bytes, size_t length, size_t charCount) 347 { 348 int32 newPosition = fPosition + length; 349 fDryRun |= (newPosition >= fBufferSize); 350 if (!fDryRun && length > 0) { 351 memcpy(fBuffer + fPosition, bytes, length); 352 fBuffer[newPosition] = '\0'; 353 } 354 fPosition = newPosition; 355 fCharCount += charCount; 356 } 357 358 void Append(const Symbol &symbol) 359 { 360 Append(symbol.symbol, symbol.length, symbol.char_count); 361 } 362 363 void Append(const Symbol *symbol) 364 { 365 if (symbol) 366 Append(*symbol); 367 } 368 369 void Append(char c, int32 count) // ASCII 128 chars only! 370 { 371 if (count <= 0) 372 return; 373 int32 newPosition = fPosition + count; 374 fDryRun |= (newPosition >= fBufferSize); 375 if (!fDryRun && count > 0) { 376 memset(fBuffer + fPosition, c, count); 377 fBuffer[newPosition] = '\0'; 378 } 379 fPosition = newPosition; 380 fCharCount += count; 381 } 382 383 void Append(const Symbol &symbol, int32 count) 384 { 385 if (count <= 0) 386 return; 387 int32 bytes = count * symbol.length; 388 int32 newPosition = fPosition + bytes; 389 fDryRun |= (newPosition >= fBufferSize); 390 if (!fDryRun && count > 0) { 391 for (int i = 0; i < count * symbol.length; i++) 392 fBuffer[i] = symbol.symbol[i % symbol.length]; 393 fBuffer[newPosition] = '\0'; 394 } 395 fPosition = newPosition; 396 fCharCount += count * symbol.char_count; 397 } 398 399 void Append(const Symbol *symbol, int32 count) 400 { 401 if (symbol) 402 Append(*symbol, count); 403 } 404 405 private: 406 char *fBuffer; 407 int32 fBufferSize; 408 int32 fPosition; 409 int32 fCharCount; 410 bool fDryRun; 411}; 412 413 414// constants 415 416// digit symbols 417const BGenericNumberFormat::Symbol 418 BGenericNumberFormat::kDefaultDigitSymbols[] = { 419 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" 420 }; 421 422// decimal separator symbol 423const BGenericNumberFormat::Symbol 424 BGenericNumberFormat::kDefaultFractionSeparator = "."; 425 426// grouping separator symbols 427static const char *kDefaultGroupingSeparators[] = { "," }; 428static const int32 kDefaultGroupingSeparatorCount 429 = sizeof(kDefaultGroupingSeparators) / sizeof(const char*); 430static const char *kNoGroupingSeparators[] = { NULL }; // to please mwcc 431static const int32 kNoGroupingSeparatorCount = 0; 432 433// grouping sizes 434static const size_t kDefaultGroupingSizes[] = { 3 }; 435static const int32 kDefaultGroupingSizeCount 436 = sizeof(kDefaultGroupingSizes) / sizeof(size_t); 437static const size_t kNoGroupingSizes[] = { 0 }; // to please mwcc 438static const int32 kNoGroupingSizeCount = 0; 439 440// grouping info 441const BGenericNumberFormat::GroupingInfo 442 BGenericNumberFormat::kDefaultGroupingInfo( 443 kDefaultGroupingSeparators, kDefaultGroupingSeparatorCount, 444 kDefaultGroupingSizes, kDefaultGroupingSizeCount 445 ); 446const BGenericNumberFormat::GroupingInfo 447 BGenericNumberFormat::kNoGroupingInfo( 448 kNoGroupingSeparators, kNoGroupingSeparatorCount, 449 kNoGroupingSizes, kNoGroupingSizeCount 450 ); 451 452// exponent symbol 453const BGenericNumberFormat::Symbol 454 BGenericNumberFormat::kDefaultExponentSymbol = "e"; 455const BGenericNumberFormat::Symbol 456 BGenericNumberFormat::kDefaultUpperCaseExponentSymbol = "E"; 457 458// NaN symbol 459const BGenericNumberFormat::Symbol 460 BGenericNumberFormat::kDefaultNaNSymbol = "NaN"; 461const BGenericNumberFormat::Symbol 462 BGenericNumberFormat::kDefaultUpperCaseNaNSymbol = "NaN"; 463 464// infinity symbol 465const BGenericNumberFormat::Symbol 466 BGenericNumberFormat::kDefaultInfinitySymbol = "infinity"; 467const BGenericNumberFormat::Symbol 468 BGenericNumberFormat::kDefaultUpperCaseInfinitySymbol = "INFINITY"; 469 470// negative infinity symbol 471const BGenericNumberFormat::Symbol 472 BGenericNumberFormat::kDefaultNegativeInfinitySymbol = "-infinity"; 473const BGenericNumberFormat::Symbol 474 BGenericNumberFormat::kDefaultUpperCaseNegativeInfinitySymbol = "-INFINITY"; 475 476// sign symbols 477const BGenericNumberFormat::SignSymbols 478 BGenericNumberFormat::kDefaultSignSymbols( 479 "+", "-", " ", "", // prefixes 480 "", "", "", "" // suffixes 481 ); 482 483// mantissa sign symbols 484const BGenericNumberFormat::SignSymbols 485 BGenericNumberFormat::kDefaultMantissaSignSymbols( 486 "", "", "", "", // prefixes 487 "", "", "", "" // suffixes 488 ); 489 490// exponent sign symbols 491const BGenericNumberFormat::SignSymbols 492 BGenericNumberFormat::kDefaultExponentSignSymbols( 493 "+", "-", " ", "", // prefixes 494 "", "", "", "" // suffixes 495 ); 496 497 498// Integer 499class BGenericNumberFormat::Integer { 500 public: 501 Integer(int64 number) 502 : fDigitCount(0), 503 fNegative(number < 0) 504 { 505 if (fNegative) 506 Init(0ULL - (uint64)number); 507 else 508 Init(number); 509 } 510 511 Integer(uint64 number) 512 : fDigitCount(0), 513 fNegative(false) 514 { 515 Init(number); 516 } 517 518 int DigitCount() const 519 { 520 return fDigitCount; 521 } 522 523 bool IsNegative() const 524 { 525 return fNegative; 526 } 527 528 char *ToString(char *str) const 529 { 530 if (fDigitCount == 0) { 531 str[0] = '0'; 532 str[1] = '\0'; 533 } else if (fNegative) { 534 str[0] = '-'; 535 for (int i = 0; i < fDigitCount; i++) 536 str[i + 1] = '0' + fDigits[fDigitCount - i - 1]; 537 str[fDigitCount + 1] = '\0'; 538 } else { 539 for (int i = 0; i < fDigitCount; i++) 540 str[i] = '0' + fDigits[fDigitCount - i - 1]; 541 str[fDigitCount] = '\0'; 542 } 543 return str; 544 } 545 546 void Format(BufferWriter &writer, const Symbol *digitSymbols, 547 const SignSymbols *signSymbols, 548 number_format_sign_policy signPolicy, 549 const GroupingInfo *groupingInfo, int32 minDigits) const 550 { 551 const Symbol *suffix = NULL; 552 // write sign prefix 553 if (fNegative) { 554 writer.Append(signSymbols->MinusPrefix()); 555 suffix = signSymbols->MinusSuffix(); 556 } else { 557 switch (signPolicy) { 558 case B_USE_NEGATIVE_SIGN_ONLY: 559 writer.Append(signSymbols->NoForcePlusPrefix()); 560 suffix = signSymbols->NoForcePlusSuffix(); 561 break; 562 case B_USE_SPACE_FOR_POSITIVE_SIGN: 563 writer.Append(signSymbols->PadPlusPrefix()); 564 suffix = signSymbols->PadPlusSuffix(); 565 break; 566 case B_USE_POSITIVE_SIGN: 567 writer.Append(signSymbols->PlusPrefix()); 568 suffix = signSymbols->PlusSuffix(); 569 break; 570 } 571 } 572 // the digits 573 if (fDigitCount == 0 && minDigits < 1) { 574 // special case for zero and less the one minimal digit 575 writer.Append(digitSymbols[0]); 576 } else { 577 // not zero or at least one minimal digit 578 if (groupingInfo) { 579 // use grouping 580 // pad with zeros up to minDigits 581 int32 digitCount = max(fDigitCount, minDigits); 582 for (int i = minDigits - 1; i >= fDigitCount; i--) { 583 if (i != digitCount - 1) 584 writer.Append(groupingInfo->SeparatorForDigit(i)); 585 writer.Append(digitSymbols[0]); 586 } 587 // write digits 588 for (int i = fDigitCount - 1; i >= 0; i--) { 589 if (i != digitCount - 1) 590 writer.Append(groupingInfo->SeparatorForDigit(i)); 591 writer.Append(digitSymbols[fDigits[i]]); 592 } 593 } else { 594 // no grouping 595 // pad with zeros up to minDigits 596 if (fDigitCount < minDigits) 597 writer.Append(digitSymbols, minDigits - fDigitCount); 598 // write digits 599 for (int i = fDigitCount - 1; i >= 0; i--) 600 writer.Append(digitSymbols[fDigits[i]]); 601 } 602 } 603 // append suffix 604 writer.Append(suffix); 605 } 606 607 private: 608 void Init(uint64 number) 609 { 610 fDigitCount = 0; 611 while (number) { 612 fDigits[fDigitCount] = number % 10; 613 number /= 10; 614 fDigitCount++; 615 } 616 } 617 618 private: 619 uchar fDigits[kMaxIntDigitCount]; 620 int32 fDigitCount; 621 bool fNegative; 622}; 623 624 625// Float 626class BGenericNumberFormat::Float { 627 public: 628 Float(double number) 629 : fNegative(signbit(number)), 630 fClass(fpclassify(number)), 631 fExponent(0), 632 fDigitCount(0) 633 { 634 // filter special cases 635 switch (fClass) { 636 case FP_NAN: 637 case FP_INFINITE: 638 return; 639 case FP_ZERO: 640 fDigits[0] = 0; 641 fDigitCount = 1; 642 return; 643 case FP_NORMAL: 644 case FP_SUBNORMAL: 645 break; 646 } 647 if (fNegative) 648 number = -number; 649 // We start with an exponent great enough to make 650 // number / 10^fExponent < 10. It may even be < 1 or 0.1. 651 // We simply cut those digits later. 652 fExponent = (int)ceil(log10(number)); 653 int shiftBy = kMaxFloatDigitCount - fExponent - 1; 654 // We don't multiply with 10^shiftBy not in one go, since for 655 // subnormal numbers 10^shiftBy will not be representable. Maybe 656 // also for normal numbers close to the limit -- so don't risk 657 // anything, for the time being. TODO: Optimize later. 658 double mantissa = number * pow(10, shiftBy / 2); 659 mantissa *= pow(10, shiftBy - shiftBy / 2); 660 // get the mantissa's digits -- we drop trailing zeros 661 int32 firstNonNull = -1; 662 for (int i = 0; i < kMaxFloatDigitCount; i++) { 663 char digit = (char)fmod(mantissa, 10); 664 if (firstNonNull < 0 && digit > 0) 665 firstNonNull = i; 666 if (firstNonNull >= 0) 667 fDigits[i - firstNonNull] = digit; 668 mantissa /= 10; 669 } 670 if (firstNonNull >= 0) 671 fDigitCount = kMaxFloatDigitCount - firstNonNull; 672 else 673 fDigitCount = 0; 674 // drop leading zeros 675 while (fDigitCount > 0 && fDigits[fDigitCount - 1] == 0) { 676 fDigitCount--; 677 fExponent--; 678 } 679 // due to rounding effects we may end up with zero: switch to its 680 // canaonical representation then 681 if (fDigitCount == 0) { 682 fExponent = 0; 683 fDigits[0] = 0; 684 fDigitCount = 1; 685 } 686 } 687 688 void Format(BufferWriter &writer, const Symbol *digitSymbols, 689 const SpecialNumberSymbols *specialNumbers, 690 const Symbol *fractionSeparator, 691 const Symbol *exponentSymbol, 692 const SignSymbols *signSymbols, 693 const SignSymbols *mantissaSignSymbols, 694 const SignSymbols *exponentSignSymbols, 695 float_format_type formatType, 696 number_format_sign_policy signPolicy, 697 const GroupingInfo *groupingInfo, 698 int32 minIntegerDigits, int32 minFractionDigits, 699 int32 maxFractionDigits, bool forceFractionSeparator, 700 bool keepTrailingFractionZeros) const 701 { 702 // deal with special numbers 703 switch (fClass) { 704 case FP_NAN: 705 writer.Append(specialNumbers->nan); 706 return; 707 case FP_INFINITE: 708 if (fNegative) 709 writer.Append(specialNumbers->negative_infinity); 710 else 711 writer.Append(specialNumbers->infinity); 712 return; 713 case FP_ZERO: 714 case FP_NORMAL: 715 case FP_SUBNORMAL: 716 break; 717 } 718 // format according to the specified format type 719 bool scientific = false; 720 switch (formatType) { 721 case B_FIXED_POINT_FLOAT_FORMAT: 722 break; 723 case B_SCIENTIFIC_FLOAT_FORMAT: 724 scientific = true; 725 break; 726 case B_AUTO_FLOAT_FORMAT: 727 // the criterion printf() uses: 728 scientific = (fExponent >= maxFractionDigits 729 || fExponent < -4); 730 break; 731 } 732 // finally invoke the respective method that does the formatting 733 if (scientific) { 734 FormatScientific(writer, digitSymbols, fractionSeparator, 735 exponentSymbol, signSymbols, mantissaSignSymbols, 736 exponentSignSymbols, signPolicy, minIntegerDigits, 737 minFractionDigits, maxFractionDigits, 738 forceFractionSeparator, keepTrailingFractionZeros); 739 } else { 740 FormatFixedPoint(writer, digitSymbols, fractionSeparator, 741 signSymbols, mantissaSignSymbols, signPolicy, groupingInfo, 742 minIntegerDigits, minFractionDigits, maxFractionDigits, 743 forceFractionSeparator, keepTrailingFractionZeros); 744 } 745 } 746 747 void FormatScientific(BufferWriter &writer, const Symbol *digitSymbols, 748 const Symbol *fractionSeparator, 749 const Symbol *exponentSymbol, 750 const SignSymbols *signSymbols, 751 const SignSymbols *mantissaSignSymbols, 752 const SignSymbols *exponentSignSymbols, 753 number_format_sign_policy signPolicy, 754 int32 minIntegerDigits, int32 minFractionDigits, 755 int32 maxFractionDigits, bool forceFractionSeparator, 756 bool keepTrailingFractionZeros) const 757 { 758 const Symbol *suffix = NULL; 759 const Symbol *mantissaSuffix = NULL; 760 // write sign prefix 761 if (fNegative) { 762 writer.Append(signSymbols->MinusPrefix()); 763 writer.Append(mantissaSignSymbols->MinusPrefix()); 764 suffix = signSymbols->MinusSuffix(); 765 mantissaSuffix = mantissaSignSymbols->MinusSuffix(); 766 } else { 767 switch (signPolicy) { 768 case B_USE_NEGATIVE_SIGN_ONLY: 769 writer.Append(signSymbols->NoForcePlusPrefix()); 770 writer.Append(mantissaSignSymbols->NoForcePlusPrefix()); 771 suffix = signSymbols->NoForcePlusSuffix(); 772 mantissaSuffix 773 = mantissaSignSymbols->NoForcePlusSuffix(); 774 break; 775 case B_USE_SPACE_FOR_POSITIVE_SIGN: 776 writer.Append(signSymbols->PadPlusPrefix()); 777 writer.Append(mantissaSignSymbols->PadPlusPrefix()); 778 suffix = signSymbols->PadPlusSuffix(); 779 mantissaSuffix = mantissaSignSymbols->PadPlusSuffix(); 780 break; 781 case B_USE_POSITIVE_SIGN: 782 writer.Append(signSymbols->PlusPrefix()); 783 writer.Append(mantissaSignSymbols->PlusPrefix()); 784 suffix = signSymbols->PlusSuffix(); 785 mantissaSuffix = mantissaSignSymbols->PlusSuffix(); 786 break; 787 } 788 } 789 // round 790 int32 exponent = fExponent; 791 char digits[kMaxFloatDigitCount]; 792 int32 integerDigits = max(minIntegerDigits, 1L); 793 int32 fractionDigits 794 = max(fDigitCount - integerDigits, minFractionDigits); 795 fractionDigits = min(fractionDigits, maxFractionDigits); 796 int32 digitCount 797 = _Round(digits, integerDigits + fractionDigits, exponent); 798 fractionDigits = digitCount - integerDigits; 799 if (keepTrailingFractionZeros) 800 fractionDigits = max(fractionDigits, minFractionDigits); 801 fractionDigits = min(fractionDigits, maxFractionDigits); 802 // the mantissa 803 // integer part 804 int32 existingIntegerDigits = min(integerDigits, digitCount); 805 for (int i = 0; i < existingIntegerDigits; i++) 806 writer.Append(digitSymbols[(int)digits[digitCount - i - 1]]); 807 // pad with zeros to get the desired number of integer digits 808 if (existingIntegerDigits < integerDigits) { 809 writer.Append(digitSymbols, 810 integerDigits - existingIntegerDigits); 811 } 812 // unless the number is 0, adjust the exponent 813 if (!_IsZero(digits, digitCount)) 814 exponent -= integerDigits - 1; 815 // fraction part 816 if (fractionDigits > 0 || forceFractionSeparator) 817 writer.Append(fractionSeparator); 818 int32 existingFractionDigits 819 = min(digitCount - integerDigits, fractionDigits); 820 for (int i = existingFractionDigits - 1; i >= 0; i--) 821 writer.Append(digitSymbols[(int)digits[i]]); 822 // pad with zeros to get the desired number of fraction digits 823 if (fractionDigits > existingFractionDigits) { 824 writer.Append(digitSymbols, 825 fractionDigits - existingFractionDigits); 826 } 827 writer.Append(mantissaSuffix); 828 // the exponent 829 writer.Append(exponentSymbol); 830 831 Integer(static_cast<int64>(exponent)).Format(writer, digitSymbols, 832 exponentSignSymbols, B_USE_POSITIVE_SIGN, &kNoGroupingInfo, 2); 833 // sign suffix 834 writer.Append(suffix); 835 } 836 837 void FormatFixedPoint(BufferWriter &writer, const Symbol *digitSymbols, 838 const Symbol *fractionSeparator, 839 const SignSymbols *signSymbols, 840 const SignSymbols *mantissaSignSymbols, 841 number_format_sign_policy signPolicy, 842 const GroupingInfo *groupingInfo, 843 int32 minIntegerDigits, int32 minFractionDigits, 844 int32 maxFractionDigits, bool forceFractionSeparator, 845 bool keepTrailingFractionZeros) const 846 { 847 const Symbol *suffix = NULL; 848 const Symbol *mantissaSuffix = NULL; 849 // write sign prefix 850 if (fNegative) { 851 writer.Append(signSymbols->MinusPrefix()); 852 writer.Append(mantissaSignSymbols->MinusPrefix()); 853 suffix = signSymbols->MinusSuffix(); 854 mantissaSuffix = mantissaSignSymbols->MinusSuffix(); 855 } else { 856 switch (signPolicy) { 857 case B_USE_NEGATIVE_SIGN_ONLY: 858 writer.Append(signSymbols->NoForcePlusPrefix()); 859 writer.Append(mantissaSignSymbols->NoForcePlusPrefix()); 860 suffix = signSymbols->NoForcePlusSuffix(); 861 mantissaSuffix 862 = mantissaSignSymbols->NoForcePlusSuffix(); 863 break; 864 case B_USE_SPACE_FOR_POSITIVE_SIGN: 865 writer.Append(signSymbols->PadPlusPrefix()); 866 writer.Append(mantissaSignSymbols->PadPlusPrefix()); 867 suffix = signSymbols->PadPlusSuffix(); 868 mantissaSuffix = mantissaSignSymbols->PadPlusSuffix(); 869 break; 870 case B_USE_POSITIVE_SIGN: 871 writer.Append(signSymbols->PlusPrefix()); 872 writer.Append(mantissaSignSymbols->PlusPrefix()); 873 suffix = signSymbols->PlusSuffix(); 874 mantissaSuffix = mantissaSignSymbols->PlusSuffix(); 875 break; 876 } 877 } 878 // round 879 int32 exponent = fExponent; 880 char digits[kMaxFloatDigitCount]; 881 int32 integerDigits = max(minIntegerDigits, exponent + 1L); 882 int32 fractionDigits 883 = max(fDigitCount - integerDigits, minFractionDigits); 884 fractionDigits = min(fractionDigits, maxFractionDigits); 885 int32 digitCount 886 = _Round(digits, integerDigits + fractionDigits, exponent); 887 fractionDigits = digitCount - integerDigits; 888 if (keepTrailingFractionZeros) 889 fractionDigits = max(fractionDigits, minFractionDigits); 890 fractionDigits = min(fractionDigits, maxFractionDigits); 891 // integer part 892 int32 existingIntegerDigits = min(integerDigits, exponent + 1); 893 existingIntegerDigits = max(existingIntegerDigits, 0L); 894 if (groupingInfo) { 895 // use grouping 896 // pad with zeros up to minDigits 897 for (int i = integerDigits - 1; 898 i >= existingIntegerDigits; 899 i--) { 900 if (i != integerDigits - 1) 901 writer.Append(groupingInfo->SeparatorForDigit(i)); 902 writer.Append(digitSymbols[0]); 903 } 904 // write digits 905 for (int i = existingIntegerDigits - 1; i >= 0; i--) { 906 if (i != integerDigits - 1) 907 writer.Append(groupingInfo->SeparatorForDigit(i)); 908 writer.Append(digitSymbols[(int)digits[ 909 digitCount - existingIntegerDigits + i]]); 910 } 911 } else { 912 // no grouping 913 // pad with zeros to get the desired number of integer digits 914 if (existingIntegerDigits < integerDigits) { 915 writer.Append(digitSymbols[0], 916 integerDigits - existingIntegerDigits); 917 } 918 // write digits 919 for (int i = 0; i < existingIntegerDigits; i++) { 920 writer.Append( 921 digitSymbols[(int)digits[digitCount - i - 1]]); 922 } 923 } 924 // fraction part 925 if (fractionDigits > 0 || forceFractionSeparator) 926 writer.Append(fractionSeparator); 927 int32 existingFractionDigits 928 = min(digitCount - existingIntegerDigits, fractionDigits); 929 for (int i = existingFractionDigits - 1; i >= 0; i--) 930 writer.Append(digitSymbols[(int)digits[i]]); 931 // pad with zeros to get the desired number of fraction digits 932 if (fractionDigits > existingFractionDigits) { 933 writer.Append(digitSymbols, 934 fractionDigits - existingFractionDigits); 935 } 936 // sign suffixes 937 writer.Append(mantissaSuffix); 938 writer.Append(suffix); 939 } 940 941 private: 942 int32 _Round(char *digits, int32 count, int32 &exponent) const 943 { 944 if (count > fDigitCount) 945 count = fDigitCount; 946 int firstNonNull = -1; 947// TODO: Non-hardcoded base-independent rounding. 948 bool carry = false; 949 if (count < fDigitCount) 950 carry = (fDigits[fDigitCount - count - 1] >= 5); 951 for (int i = 0; i < count; i++) { 952 char digit = fDigits[fDigitCount - count + i]; 953 if (carry) { 954 digit++; 955 if (digit == 10) // == base 956 digit = 0; 957 else 958 carry = false; 959 } 960 if (firstNonNull < 0 && digit > 0) 961 firstNonNull = i; 962 if (firstNonNull >= 0) 963 digits[i - firstNonNull] = digit; 964 } 965 if (firstNonNull < 0) { 966 if (carry) { 967 // 9.999999... -> 10 968 digits[0] = 1; 969 exponent++; 970 } else { 971 // 0.0000...1 -> 0 972 exponent = 0; 973 digits[0] = 0; 974 } 975 count = 1; 976 } else 977 count -= firstNonNull; 978 return count; 979 } 980 981 static bool _IsZero(const char *digits, int32 digitCount) 982 { 983 return (digitCount == 1 && digits[0] == 0); 984 } 985 986 private: 987 bool fNegative; 988 int fClass; 989 int32 fExponent; 990 char fDigits[kMaxFloatDigitCount]; 991 int32 fDigitCount; 992}; 993 994 995// constructor 996BGenericNumberFormat::BGenericNumberFormat() 997 : fIntegerParameters(), 998 fFloatParameters(), 999 fDigitSymbols(NULL), 1000 fFractionSeparator(NULL), 1001 fGroupingInfo(NULL), 1002 fExponentSymbol(NULL), 1003 fUpperCaseExponentSymbol(NULL), 1004 fNaNSymbol(NULL), 1005 fUpperCaseNaNSymbol(NULL), 1006 fInfinitySymbol(NULL), 1007 fUpperCaseInfinitySymbol(NULL), 1008 fNegativeInfinitySymbol(NULL), 1009 fUpperCaseNegativeInfinitySymbol(NULL), 1010 fSignSymbols(NULL), 1011 fMantissaSignSymbols(NULL), 1012 fExponentSignSymbols(NULL) 1013{ 1014} 1015 1016// destructor 1017BGenericNumberFormat::~BGenericNumberFormat() 1018{ 1019 delete fSignSymbols; 1020 delete fMantissaSignSymbols; 1021 delete fExponentSignSymbols; 1022} 1023 1024// FormatInteger 1025status_t 1026BGenericNumberFormat::FormatInteger( 1027 const BIntegerFormatParameters *parameters, int64 number, BString *buffer, 1028 format_field_position *positions, int32 positionCount, int32 *fieldCount, 1029 bool allFieldPositions) const 1030{ 1031 if (!buffer) 1032 return B_BAD_VALUE; 1033 char localBuffer[1024]; 1034 status_t error = FormatInteger(parameters, number, localBuffer, 1035 sizeof(localBuffer), positions, positionCount, fieldCount, 1036 allFieldPositions); 1037 if (error == B_OK) { 1038 buffer->Append(localBuffer); 1039 // TODO: Check, if the allocation succeeded. 1040 } 1041 return error; 1042} 1043 1044// FormatInteger 1045status_t 1046BGenericNumberFormat::FormatInteger( 1047 const BIntegerFormatParameters *parameters, uint64 number, BString *buffer, 1048 format_field_position *positions, int32 positionCount, int32 *fieldCount, 1049 bool allFieldPositions) const 1050{ 1051 if (!buffer) 1052 return B_BAD_VALUE; 1053 char localBuffer[1024]; 1054 status_t error = FormatInteger(parameters, number, localBuffer, 1055 sizeof(localBuffer), positions, positionCount, fieldCount, 1056 allFieldPositions); 1057 if (error == B_OK) { 1058 buffer->Append(localBuffer); 1059 // TODO: Check, if the allocation succeeded. 1060 } 1061 return error; 1062} 1063 1064// FormatInteger 1065status_t 1066BGenericNumberFormat::FormatInteger( 1067 const BIntegerFormatParameters *parameters, int64 number, char *buffer, 1068 size_t bufferSize, format_field_position *positions, int32 positionCount, 1069 int32 *fieldCount, bool allFieldPositions) const 1070{ 1071 Integer integer(number); 1072 return FormatInteger(parameters, integer, buffer, bufferSize, positions, 1073 positionCount, fieldCount, allFieldPositions); 1074} 1075 1076// FormatInteger 1077status_t 1078BGenericNumberFormat::FormatInteger( 1079 const BIntegerFormatParameters *parameters, uint64 number, char *buffer, 1080 size_t bufferSize, format_field_position *positions, int32 positionCount, 1081 int32 *fieldCount, bool allFieldPositions) const 1082{ 1083 Integer integer(number); 1084 return FormatInteger(parameters, integer, buffer, bufferSize, positions, 1085 positionCount, fieldCount, allFieldPositions); 1086} 1087 1088// FormatFloat 1089status_t 1090BGenericNumberFormat::FormatFloat(const BFloatFormatParameters *parameters, 1091 double number, BString *buffer, format_field_position *positions, 1092 int32 positionCount, int32 *fieldCount, bool allFieldPositions) const 1093{ 1094 if (!buffer) 1095 return B_BAD_VALUE; 1096 // TODO: How to ensure that this is enough? 1097 char localBuffer[1024]; 1098 status_t error = FormatFloat(parameters, number, localBuffer, 1099 sizeof(localBuffer), positions, positionCount, fieldCount, 1100 allFieldPositions); 1101 if (error == B_OK) { 1102 buffer->Append(localBuffer); 1103 // TODO: Check, if the allocation succeeded. 1104 } 1105 return error; 1106} 1107 1108// FormatFloat 1109status_t 1110BGenericNumberFormat::FormatFloat(const BFloatFormatParameters *parameters, 1111 double number, char *buffer, size_t bufferSize, 1112 format_field_position *positions, int32 positionCount, int32 *fieldCount, 1113 bool allFieldPositions) const 1114{ 1115 // TODO: Check parameters. 1116 if (!parameters) 1117 parameters = DefaultFloatFormatParameters(); 1118 if (bufferSize <= parameters->FormatWidth()) 1119 return EOVERFLOW; 1120 Float floatNumber(number); 1121 // prepare some parameters 1122 const GroupingInfo *groupingInfo = NULL; 1123 if (parameters->UseGrouping()) 1124 groupingInfo = GetGroupingInfo(); 1125 bool upperCase = parameters->UseUpperCase(); 1126 SpecialNumberSymbols specialSymbols; 1127 GetSpecialNumberSymbols(upperCase, &specialSymbols); 1128 // compute the length of the formatted string 1129 BufferWriter writer; 1130 floatNumber.Format(writer, DigitSymbols(), &specialSymbols, 1131 FractionSeparator(), ExponentSymbol(), GetSignSymbols(), 1132 MantissaSignSymbols(), ExponentSignSymbols(), 1133 parameters->FloatFormatType(), parameters->SignPolicy(), groupingInfo, 1134 parameters->MinimalIntegerDigits(), parameters->MinimalFractionDigits(), 1135 parameters->MaximalFractionDigits(), 1136 parameters->AlwaysUseFractionSeparator(), 1137 parameters->KeepTrailingFractionZeros()); 1138 int32 stringLength = writer.StringLength(); 1139 int32 charCount = writer.CharCount(); 1140 // consider alignment and check the available space in the buffer 1141 int32 padding = max(0L, (int32)parameters->FormatWidth() - charCount); 1142// TODO: Padding with zeros. 1143 if ((int32)bufferSize <= stringLength + padding) 1144 return EOVERFLOW; 1145 // prepare for writing 1146 writer.SetTo(buffer, bufferSize); 1147 // write padding for right field alignment 1148 if (parameters->Alignment() == B_ALIGN_FORMAT_RIGHT && padding > 0) 1149 writer.Append(' ', padding); 1150 // write the number 1151 floatNumber.Format(writer, DigitSymbols(), &specialSymbols, 1152 FractionSeparator(), ExponentSymbol(), GetSignSymbols(), 1153 MantissaSignSymbols(), ExponentSignSymbols(), 1154 parameters->FloatFormatType(), parameters->SignPolicy(), groupingInfo, 1155 parameters->MinimalIntegerDigits(), parameters->MinimalFractionDigits(), 1156 parameters->MaximalFractionDigits(), 1157 parameters->AlwaysUseFractionSeparator(), 1158 parameters->KeepTrailingFractionZeros()); 1159 // write padding for left field alignment 1160 if (parameters->Alignment() == B_ALIGN_FORMAT_LEFT && padding > 0) 1161 writer.Append(' ', padding); 1162 return B_OK; 1163} 1164 1165// SetDefaultIntegerFormatParameters 1166status_t 1167BGenericNumberFormat::SetDefaultIntegerFormatParameters( 1168 const BIntegerFormatParameters *parameters) 1169{ 1170 if (!parameters) 1171 return B_BAD_VALUE; 1172 fIntegerParameters = *parameters; 1173 return B_OK; 1174} 1175 1176// DefaultIntegerFormatParameters 1177BIntegerFormatParameters * 1178BGenericNumberFormat::DefaultIntegerFormatParameters() 1179{ 1180 return &fIntegerParameters; 1181} 1182 1183// DefaultIntegerFormatParameters 1184const BIntegerFormatParameters * 1185BGenericNumberFormat::DefaultIntegerFormatParameters() const 1186{ 1187 return &fIntegerParameters; 1188} 1189 1190// SetDefaultFloatFormatParameters 1191status_t 1192BGenericNumberFormat::SetDefaultFloatFormatParameters( 1193 const BFloatFormatParameters *parameters) 1194{ 1195 if (!parameters) 1196 return B_BAD_VALUE; 1197 fFloatParameters = *parameters; 1198 return B_OK; 1199} 1200 1201// DefaultFloatFormatParameters 1202BFloatFormatParameters * 1203BGenericNumberFormat::DefaultFloatFormatParameters() 1204{ 1205 return &fFloatParameters; 1206} 1207 1208// DefaultFloatFormatParameters 1209const BFloatFormatParameters * 1210BGenericNumberFormat::DefaultFloatFormatParameters() const 1211{ 1212 return &fFloatParameters; 1213} 1214 1215// SetDigitSymbols 1216status_t 1217BGenericNumberFormat::SetDigitSymbols(const char **digits) 1218{ 1219 // check parameters 1220 if (digits) { 1221 for (int i = 0; i < 10; i++) { 1222 if (!digits[i]) 1223 return B_BAD_VALUE; 1224 } 1225 } 1226 // unset old 1227 if (fDigitSymbols) { 1228 delete[] fDigitSymbols; 1229 fDigitSymbols = NULL; 1230 } 1231 // set new 1232 if (digits) { 1233 fDigitSymbols = new(nothrow) Symbol[10]; 1234 if (!fDigitSymbols) 1235 return B_NO_MEMORY; 1236 for (int i = 0; i < 10; i++) { 1237 status_t error = fDigitSymbols[i].SetTo(digits[i]); 1238 if (error != B_OK) { 1239 SetDigitSymbols(NULL); 1240 return error; 1241 } 1242 } 1243 } 1244 return B_OK; 1245} 1246 1247// SetFractionSeparator 1248status_t 1249BGenericNumberFormat::SetFractionSeparator(const char *decimalSeparator) 1250{ 1251 return _SetSymbol(&fFractionSeparator, decimalSeparator); 1252} 1253 1254// SetGroupingInfo 1255status_t 1256BGenericNumberFormat::SetGroupingInfo(const char **groupingSeparators, 1257 size_t separatorCount, size_t *groupingSizes, size_t sizeCount) 1258{ 1259 // check parameters 1260 if (groupingSeparators && separatorCount > 0 && groupingSizes 1261 && sizeCount) { 1262 for (int i = 0; i < (int)separatorCount; i++) { 1263 if (!groupingSeparators[i]) 1264 return B_BAD_VALUE; 1265 } 1266 } 1267 // unset old 1268 if (fGroupingInfo) { 1269 delete fGroupingInfo; 1270 fGroupingInfo = NULL; 1271 } 1272 // set new 1273 if (groupingSeparators && separatorCount > 0 && groupingSizes 1274 && sizeCount) { 1275 fGroupingInfo = new GroupingInfo; 1276 if (!fGroupingInfo) 1277 return B_NO_MEMORY; 1278 status_t error = fGroupingInfo->SetTo(groupingSeparators, 1279 separatorCount, groupingSizes, sizeCount); 1280 if (error != B_OK) { 1281 delete fGroupingInfo; 1282 fGroupingInfo = NULL; 1283 return error; 1284 } 1285 } 1286 return B_OK; 1287} 1288 1289// SetExponentSymbol 1290status_t 1291BGenericNumberFormat::SetExponentSymbol(const char *exponentSymbol, 1292 const char *upperCaseExponentSymbol) 1293{ 1294 status_t error = _SetSymbol(&fExponentSymbol, exponentSymbol); 1295 if (error == B_OK) 1296 error = _SetSymbol(&fUpperCaseExponentSymbol, upperCaseExponentSymbol); 1297 if (error != B_OK) 1298 SetExponentSymbol(NULL, NULL); 1299 return error; 1300} 1301 1302// SetSpecialNumberSymbols 1303status_t 1304BGenericNumberFormat::SetSpecialNumberSymbols(const char *nan, 1305 const char *infinity, const char *negativeInfinity, 1306 const char *upperCaseNaN, const char *upperCaseInfinity, 1307 const char *upperCaseNegativeInfinity) 1308{ 1309 status_t error = _SetSymbol(&fNaNSymbol, nan); 1310 if (error == B_OK) 1311 error = _SetSymbol(&fInfinitySymbol, infinity); 1312 if (error == B_OK) 1313 error = _SetSymbol(&fNegativeInfinitySymbol, negativeInfinity); 1314 if (error == B_OK) 1315 error = _SetSymbol(&fUpperCaseNaNSymbol, upperCaseNaN); 1316 if (error == B_OK) 1317 error = _SetSymbol(&fUpperCaseInfinitySymbol, upperCaseInfinity); 1318 if (error == B_OK) { 1319 error = _SetSymbol(&fUpperCaseNegativeInfinitySymbol, 1320 upperCaseNegativeInfinity); 1321 } 1322 if (error != B_OK) 1323 SetSpecialNumberSymbols(NULL, NULL, NULL, NULL, NULL, NULL); 1324 return error; 1325} 1326 1327// SetSignSymbols 1328status_t 1329BGenericNumberFormat::SetSignSymbols(const char *plusPrefix, 1330 const char *minusPrefix, const char *padPlusPrefix, 1331 const char *noForcePlusPrefix, const char *plusSuffix, 1332 const char *minusSuffix, const char *padPlusSuffix, 1333 const char *noForcePlusSuffix) 1334{ 1335 if (!fSignSymbols) { 1336 fSignSymbols = new(nothrow) SignSymbols; 1337 if (!fSignSymbols) 1338 return B_NO_MEMORY; 1339 } 1340 return fSignSymbols->SetTo(plusPrefix, minusPrefix, padPlusPrefix, 1341 noForcePlusPrefix, plusSuffix, minusSuffix, padPlusSuffix, 1342 noForcePlusSuffix); 1343} 1344 1345// SetMantissaSignSymbols 1346status_t 1347BGenericNumberFormat::SetMantissaSignSymbols(const char *plusPrefix, 1348 const char *minusPrefix, const char *padPlusPrefix, 1349 const char *noForcePlusPrefix, const char *plusSuffix, 1350 const char *minusSuffix, const char *padPlusSuffix, 1351 const char *noForcePlusSuffix) 1352{ 1353 if (!fMantissaSignSymbols) { 1354 fMantissaSignSymbols = new(nothrow) SignSymbols; 1355 if (!fMantissaSignSymbols) 1356 return B_NO_MEMORY; 1357 } 1358 return fMantissaSignSymbols->SetTo(plusPrefix, minusPrefix, padPlusPrefix, 1359 noForcePlusPrefix, plusSuffix, minusSuffix, padPlusSuffix, 1360 noForcePlusSuffix); 1361} 1362 1363// SetExponentSignSymbols 1364status_t 1365BGenericNumberFormat::SetExponentSignSymbols(const char *plusPrefix, 1366 const char *minusPrefix, const char *plusSuffix, const char *minusSuffix) 1367{ 1368 if (!fExponentSignSymbols) { 1369 fExponentSignSymbols = new(nothrow) SignSymbols; 1370 if (!fExponentSignSymbols) 1371 return B_NO_MEMORY; 1372 } 1373 return fExponentSignSymbols->SetTo(plusPrefix, minusPrefix, plusPrefix, 1374 plusPrefix, plusSuffix, minusSuffix, plusSuffix, plusSuffix); 1375} 1376 1377// FormatInteger 1378status_t 1379BGenericNumberFormat::FormatInteger( 1380 const BIntegerFormatParameters *parameters, const Integer &integer, 1381 char *buffer, size_t bufferSize, format_field_position *positions, 1382 int32 positionCount, int32 *fieldCount, bool allFieldPositions) const 1383{ 1384 // TODO: Check parameters. 1385 if (!parameters) 1386 parameters = DefaultIntegerFormatParameters(); 1387 if (bufferSize <= parameters->FormatWidth()) 1388 return EOVERFLOW; 1389 // prepare some parameters 1390 const GroupingInfo *groupingInfo = NULL; 1391 if (parameters->UseGrouping()) 1392 groupingInfo = GetGroupingInfo(); 1393 // compute the length of the formatted string 1394 BufferWriter writer; 1395 integer.Format(writer, DigitSymbols(), 1396 GetSignSymbols(), parameters->SignPolicy(), groupingInfo, 1397 parameters->MinimalIntegerDigits()); 1398 int32 stringLength = writer.StringLength(); 1399 int32 charCount = writer.CharCount(); 1400 // consider alignment and check the available space in the buffer 1401 int32 padding = max(0L, (int32)parameters->FormatWidth() - charCount); 1402// TODO: Padding with zeros. 1403 if ((int32)bufferSize <= stringLength + padding) 1404 return EOVERFLOW; 1405 // prepare for writing 1406 writer.SetTo(buffer, bufferSize); 1407 // write padding for right field alignment 1408 if (parameters->Alignment() == B_ALIGN_FORMAT_RIGHT && padding > 0) 1409 writer.Append(' ', padding); 1410 // write the number 1411 integer.Format(writer, DigitSymbols(), 1412 GetSignSymbols(), parameters->SignPolicy(), groupingInfo, 1413 parameters->MinimalIntegerDigits()); 1414 // write padding for left field alignment 1415 if (parameters->Alignment() == B_ALIGN_FORMAT_LEFT && padding > 0) 1416 writer.Append(' ', padding); 1417 return B_OK; 1418} 1419 1420// DigitSymbols 1421const BGenericNumberFormat::Symbol * 1422BGenericNumberFormat::DigitSymbols() const 1423{ 1424 return (fDigitSymbols ? fDigitSymbols : kDefaultDigitSymbols); 1425} 1426 1427// FractionSeparator 1428const BGenericNumberFormat::Symbol * 1429BGenericNumberFormat::FractionSeparator() const 1430{ 1431 return (fFractionSeparator ? fFractionSeparator 1432 : &kDefaultFractionSeparator); 1433} 1434 1435// GetGroupingInfo 1436const BGenericNumberFormat::GroupingInfo * 1437BGenericNumberFormat::GetGroupingInfo() const 1438{ 1439 return (fGroupingInfo ? fGroupingInfo : &kDefaultGroupingInfo); 1440} 1441 1442// ExponentSymbol 1443const BGenericNumberFormat::Symbol * 1444BGenericNumberFormat::ExponentSymbol(bool upperCase) const 1445{ 1446 if (fExponentSymbol) { 1447 return (upperCase && fUpperCaseExponentSymbol ? fUpperCaseExponentSymbol 1448 : fExponentSymbol); 1449 } 1450 return (upperCase ? &kDefaultUpperCaseExponentSymbol 1451 : &kDefaultExponentSymbol); 1452} 1453 1454// NaNSymbol 1455const BGenericNumberFormat::Symbol * 1456BGenericNumberFormat::NaNSymbol(bool upperCase) const 1457{ 1458 if (fNaNSymbol) { 1459 return (upperCase && fUpperCaseNaNSymbol ? fUpperCaseNaNSymbol 1460 : fNaNSymbol); 1461 } 1462 return (upperCase ? &kDefaultUpperCaseNaNSymbol 1463 : &kDefaultNaNSymbol); 1464} 1465 1466// InfinitySymbol 1467const BGenericNumberFormat::Symbol * 1468BGenericNumberFormat::InfinitySymbol(bool upperCase) const 1469{ 1470 if (fInfinitySymbol) { 1471 return (upperCase && fUpperCaseInfinitySymbol ? fUpperCaseInfinitySymbol 1472 : fInfinitySymbol); 1473 } 1474 return (upperCase ? &kDefaultUpperCaseInfinitySymbol 1475 : &kDefaultInfinitySymbol); 1476} 1477 1478// NegativeInfinitySymbol 1479const BGenericNumberFormat::Symbol * 1480BGenericNumberFormat::NegativeInfinitySymbol(bool upperCase) const 1481{ 1482 if (fNegativeInfinitySymbol) { 1483 return (upperCase && fUpperCaseNegativeInfinitySymbol 1484 ? fUpperCaseNegativeInfinitySymbol : fNegativeInfinitySymbol); 1485 } 1486 return (upperCase ? &kDefaultUpperCaseNegativeInfinitySymbol 1487 : &kDefaultNegativeInfinitySymbol); 1488} 1489 1490// GetSpecialNumberSymbols 1491void 1492BGenericNumberFormat::GetSpecialNumberSymbols(bool upperCase, 1493 SpecialNumberSymbols *symbols) const 1494{ 1495 symbols->nan = NaNSymbol(upperCase); 1496 symbols->infinity = InfinitySymbol(upperCase); 1497 symbols->negative_infinity = NegativeInfinitySymbol(upperCase); 1498} 1499 1500// GetSignSymbols 1501const BGenericNumberFormat::SignSymbols * 1502BGenericNumberFormat::GetSignSymbols() const 1503{ 1504 return (fSignSymbols ? fSignSymbols : &kDefaultSignSymbols); 1505} 1506 1507// MantissaSignSymbols 1508const BGenericNumberFormat::SignSymbols * 1509BGenericNumberFormat::MantissaSignSymbols() const 1510{ 1511 return (fMantissaSignSymbols ? fMantissaSignSymbols 1512 : &kDefaultMantissaSignSymbols); 1513} 1514 1515// ExponentSignSymbols 1516const BGenericNumberFormat::SignSymbols * 1517BGenericNumberFormat::ExponentSignSymbols() const 1518{ 1519 return (fExponentSignSymbols ? fExponentSignSymbols 1520 : &kDefaultExponentSignSymbols); 1521} 1522 1523// _SetSymbol 1524status_t 1525BGenericNumberFormat::_SetSymbol(Symbol **symbol, const char *str) 1526{ 1527 if (!str) { 1528 // no symbol -- unset old 1529 if (*symbol) { 1530 delete *symbol; 1531 symbol = NULL; 1532 } 1533 } else { 1534 // allocate if not existing 1535 if (!*symbol) { 1536 *symbol = new(nothrow) Symbol; 1537 if (!*symbol) 1538 return B_NO_MEMORY; 1539 } 1540 // set symbol 1541 status_t error = (*symbol)->SetTo(str); 1542 if (error != B_OK) { 1543 delete *symbol; 1544 *symbol = NULL; 1545 return B_NO_MEMORY; 1546 } 1547 } 1548 return B_OK; 1549} 1550 1551