BPicture: Fix archive constructor.
[haiku.git] / src / kits / locale / GenericNumberFormat.cpp
blobd1e63ec0734c51dc8ea3206504c981d3051bb126
1 #include <algorithm>
2 #include <float.h>
3 #include <math.h>
4 #include <new>
5 #include <stdlib.h>
7 #include <GenericNumberFormat.h>
8 #include <String.h>
9 #include <UnicodeChar.h>
11 #if __GNUC__ > 2
12 using std::max;
13 using std::min;
14 using std::nothrow;
15 #endif
17 // constants (more below the helper classes)
19 static const int kMaxIntDigitCount = 20; // int64: 19 + sign, uint64: 20
20 static const int kMaxFloatDigitCount = DBL_DIG + 2;
21 // double: mantissa precision + 2
24 // Symbol
26 // constructor
27 BGenericNumberFormat::Symbol::Symbol(const char *symbol)
28 : symbol(NULL),
29 length(0),
30 char_count(0)
32 SetTo(symbol);
35 // destructor
36 BGenericNumberFormat::Symbol::~Symbol()
38 Unset();
41 // SetTo
42 status_t
43 BGenericNumberFormat::Symbol::SetTo(const char *symbol)
45 // unset old
46 if (this->symbol) {
47 free(this->symbol);
48 length = 0;
49 char_count = 0;
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);
59 return B_OK;
63 // SpecialNumberSymbols
64 struct BGenericNumberFormat::SpecialNumberSymbols {
65 const Symbol *nan;
66 const Symbol *infinity;
67 const Symbol *negative_infinity;
71 // GroupingInfo
72 class BGenericNumberFormat::GroupingInfo {
73 public:
74 GroupingInfo()
75 : fSeparators(NULL),
76 fSeparatorCount(0),
77 fSizes(NULL),
78 fSizeCount(0),
79 fSumSizes(NULL),
80 fSumSeparators(NULL)
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)
93 SetTo(separators, separatorCount, sizes, sizeCount);
96 ~GroupingInfo()
98 Unset();
101 status_t SetTo(const char **separators, int32 separatorCount,
102 const size_t *sizes, int32 sizeCount)
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;
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;
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)];
137 return B_OK;
140 void Unset()
142 if (fSeparators) {
143 delete[] fSeparators;
144 fSeparators = NULL;
146 fSeparatorCount = 0;
147 if (fSizes) {
148 delete[] fSizes;
149 fSizes = NULL;
151 fSizeCount = 0;
152 if (fSumSizes) {
153 delete[] fSumSizes;
154 fSumSizes = NULL;
156 if (fSumSeparators) {
157 delete[] fSumSeparators;
158 fSumSeparators = NULL;
162 const Symbol *SeparatorForDigit(int32 position) const
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];
171 return NULL;
174 return NULL;
177 private:
178 Symbol *fSeparators;
179 int32 fSeparatorCount;
180 int32 *fSizes;
181 int32 fSizeCount;
182 int32 *fSumSizes;
183 Symbol **fSumSeparators;
187 // SignSymbols
188 class BGenericNumberFormat::SignSymbols {
189 public:
190 SignSymbols()
191 : fPlusPrefix(),
192 fMinusPrefix(),
193 fPadPlusPrefix(),
194 fNoForcePlusPrefix(),
195 fPlusSuffix(),
196 fMinusSuffix(),
197 fPadPlusSuffix(),
198 fNoForcePlusSuffix()
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)
217 ~SignSymbols()
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)
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;
248 void Unset()
250 fPlusPrefix.Unset();
251 fMinusPrefix.Unset();
252 fNoForcePlusPrefix.Unset();
253 fPadPlusPrefix.Unset();
254 fPlusSuffix.Unset();
255 fMinusSuffix.Unset();
256 fNoForcePlusSuffix.Unset();
257 fPadPlusSuffix.Unset();
260 const Symbol *PlusPrefix() const
262 return &fPlusPrefix;
265 const Symbol *MinusPrefix() const
267 return &fMinusPrefix;
270 const Symbol *PadPlusPrefix() const
272 return &fPadPlusPrefix;
275 const Symbol *NoForcePlusPrefix() const
277 return &fNoForcePlusPrefix;
280 const Symbol *PlusSuffix() const
282 return &fPlusSuffix;
285 const Symbol *MinusSuffix() const
287 return &fMinusSuffix;
290 const Symbol *PadPlusSuffix() const
292 return &fPadPlusSuffix;
295 const Symbol *NoForcePlusSuffix() const
297 return &fNoForcePlusSuffix;
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;
312 // BufferWriter
313 class BGenericNumberFormat::BufferWriter {
314 public:
315 BufferWriter(char *buffer = NULL, int32 bufferSize = 0)
317 SetTo(buffer, bufferSize);
320 void SetTo(char *buffer = NULL, int32 bufferSize = 0)
322 fBuffer = buffer;
323 fBufferSize = bufferSize;
324 fPosition = 0;
325 fCharCount = 0;
326 fDryRun = (!fBuffer || (fBufferSize == 0));
327 if (!fDryRun)
328 fBuffer[0] = '\0';
331 int32 StringLength() const
333 return fPosition;
336 int32 CharCount() const
338 return fCharCount;
341 bool IsOverflow() const
343 return (fPosition >= fBufferSize);
346 void Append(const char *bytes, size_t length, size_t charCount)
348 int32 newPosition = fPosition + length;
349 fDryRun |= (newPosition >= fBufferSize);
350 if (!fDryRun && length > 0) {
351 memcpy(fBuffer + fPosition, bytes, length);
352 fBuffer[newPosition] = '\0';
354 fPosition = newPosition;
355 fCharCount += charCount;
358 void Append(const Symbol &symbol)
360 Append(symbol.symbol, symbol.length, symbol.char_count);
363 void Append(const Symbol *symbol)
365 if (symbol)
366 Append(*symbol);
369 void Append(char c, int32 count) // ASCII 128 chars only!
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';
379 fPosition = newPosition;
380 fCharCount += count;
383 void Append(const Symbol &symbol, int32 count)
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';
395 fPosition = newPosition;
396 fCharCount += count * symbol.char_count;
399 void Append(const Symbol *symbol, int32 count)
401 if (symbol)
402 Append(*symbol, count);
405 private:
406 char *fBuffer;
407 int32 fBufferSize;
408 int32 fPosition;
409 int32 fCharCount;
410 bool fDryRun;
414 // constants
416 // digit symbols
417 const BGenericNumberFormat::Symbol
418 BGenericNumberFormat::kDefaultDigitSymbols[] = {
419 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
422 // decimal separator symbol
423 const BGenericNumberFormat::Symbol
424 BGenericNumberFormat::kDefaultFractionSeparator = ".";
426 // grouping separator symbols
427 static const char *kDefaultGroupingSeparators[] = { "," };
428 static const int32 kDefaultGroupingSeparatorCount
429 = sizeof(kDefaultGroupingSeparators) / sizeof(const char*);
430 static const char *kNoGroupingSeparators[] = { NULL }; // to please mwcc
431 static const int32 kNoGroupingSeparatorCount = 0;
433 // grouping sizes
434 static const size_t kDefaultGroupingSizes[] = { 3 };
435 static const int32 kDefaultGroupingSizeCount
436 = sizeof(kDefaultGroupingSizes) / sizeof(size_t);
437 static const size_t kNoGroupingSizes[] = { 0 }; // to please mwcc
438 static const int32 kNoGroupingSizeCount = 0;
440 // grouping info
441 const BGenericNumberFormat::GroupingInfo
442 BGenericNumberFormat::kDefaultGroupingInfo(
443 kDefaultGroupingSeparators, kDefaultGroupingSeparatorCount,
444 kDefaultGroupingSizes, kDefaultGroupingSizeCount
446 const BGenericNumberFormat::GroupingInfo
447 BGenericNumberFormat::kNoGroupingInfo(
448 kNoGroupingSeparators, kNoGroupingSeparatorCount,
449 kNoGroupingSizes, kNoGroupingSizeCount
452 // exponent symbol
453 const BGenericNumberFormat::Symbol
454 BGenericNumberFormat::kDefaultExponentSymbol = "e";
455 const BGenericNumberFormat::Symbol
456 BGenericNumberFormat::kDefaultUpperCaseExponentSymbol = "E";
458 // NaN symbol
459 const BGenericNumberFormat::Symbol
460 BGenericNumberFormat::kDefaultNaNSymbol = "NaN";
461 const BGenericNumberFormat::Symbol
462 BGenericNumberFormat::kDefaultUpperCaseNaNSymbol = "NaN";
464 // infinity symbol
465 const BGenericNumberFormat::Symbol
466 BGenericNumberFormat::kDefaultInfinitySymbol = "infinity";
467 const BGenericNumberFormat::Symbol
468 BGenericNumberFormat::kDefaultUpperCaseInfinitySymbol = "INFINITY";
470 // negative infinity symbol
471 const BGenericNumberFormat::Symbol
472 BGenericNumberFormat::kDefaultNegativeInfinitySymbol = "-infinity";
473 const BGenericNumberFormat::Symbol
474 BGenericNumberFormat::kDefaultUpperCaseNegativeInfinitySymbol = "-INFINITY";
476 // sign symbols
477 const BGenericNumberFormat::SignSymbols
478 BGenericNumberFormat::kDefaultSignSymbols(
479 "+", "-", " ", "", // prefixes
480 "", "", "", "" // suffixes
483 // mantissa sign symbols
484 const BGenericNumberFormat::SignSymbols
485 BGenericNumberFormat::kDefaultMantissaSignSymbols(
486 "", "", "", "", // prefixes
487 "", "", "", "" // suffixes
490 // exponent sign symbols
491 const BGenericNumberFormat::SignSymbols
492 BGenericNumberFormat::kDefaultExponentSignSymbols(
493 "+", "-", " ", "", // prefixes
494 "", "", "", "" // suffixes
498 // Integer
499 class BGenericNumberFormat::Integer {
500 public:
501 Integer(int64 number)
502 : fDigitCount(0),
503 fNegative(number < 0)
505 if (fNegative)
506 Init(0ULL - (uint64)number);
507 else
508 Init(number);
511 Integer(uint64 number)
512 : fDigitCount(0),
513 fNegative(false)
515 Init(number);
518 int DigitCount() const
520 return fDigitCount;
523 bool IsNegative() const
525 return fNegative;
528 char *ToString(char *str) const
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';
543 return str;
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
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;
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]);
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]]);
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]]);
603 // append suffix
604 writer.Append(suffix);
607 private:
608 void Init(uint64 number)
610 fDigitCount = 0;
611 while (number) {
612 fDigits[fDigitCount] = number % 10;
613 number /= 10;
614 fDigitCount++;
618 private:
619 uchar fDigits[kMaxIntDigitCount];
620 int32 fDigitCount;
621 bool fNegative;
625 // Float
626 class BGenericNumberFormat::Float {
627 public:
628 Float(double number)
629 : fNegative(signbit(number)),
630 fClass(fpclassify(number)),
631 fExponent(0),
632 fDigitCount(0)
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;
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;
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--;
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;
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
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;
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;
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);
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
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;
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);
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);
827 writer.Append(mantissaSuffix);
828 // the exponent
829 writer.Append(exponentSymbol);
831 Integer(static_cast<int64>(exponent)).Format(writer, digitSymbols,
832 exponentSignSymbols, B_USE_POSITIVE_SIGN, &kNoGroupingInfo, 2);
833 // sign suffix
834 writer.Append(suffix);
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
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;
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]);
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]]);
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);
918 // write digits
919 for (int i = 0; i < existingIntegerDigits; i++) {
920 writer.Append(
921 digitSymbols[(int)digits[digitCount - i - 1]]);
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);
936 // sign suffixes
937 writer.Append(mantissaSuffix);
938 writer.Append(suffix);
941 private:
942 int32 _Round(char *digits, int32 count, int32 &exponent) const
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;
960 if (firstNonNull < 0 && digit > 0)
961 firstNonNull = i;
962 if (firstNonNull >= 0)
963 digits[i - firstNonNull] = digit;
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;
975 count = 1;
976 } else
977 count -= firstNonNull;
978 return count;
981 static bool _IsZero(const char *digits, int32 digitCount)
983 return (digitCount == 1 && digits[0] == 0);
986 private:
987 bool fNegative;
988 int fClass;
989 int32 fExponent;
990 char fDigits[kMaxFloatDigitCount];
991 int32 fDigitCount;
995 // constructor
996 BGenericNumberFormat::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)
1016 // destructor
1017 BGenericNumberFormat::~BGenericNumberFormat()
1019 delete fSignSymbols;
1020 delete fMantissaSignSymbols;
1021 delete fExponentSignSymbols;
1024 // FormatInteger
1025 status_t
1026 BGenericNumberFormat::FormatInteger(
1027 const BIntegerFormatParameters *parameters, int64 number, BString *buffer,
1028 format_field_position *positions, int32 positionCount, int32 *fieldCount,
1029 bool allFieldPositions) const
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.
1041 return error;
1044 // FormatInteger
1045 status_t
1046 BGenericNumberFormat::FormatInteger(
1047 const BIntegerFormatParameters *parameters, uint64 number, BString *buffer,
1048 format_field_position *positions, int32 positionCount, int32 *fieldCount,
1049 bool allFieldPositions) const
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.
1061 return error;
1064 // FormatInteger
1065 status_t
1066 BGenericNumberFormat::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
1071 Integer integer(number);
1072 return FormatInteger(parameters, integer, buffer, bufferSize, positions,
1073 positionCount, fieldCount, allFieldPositions);
1076 // FormatInteger
1077 status_t
1078 BGenericNumberFormat::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
1083 Integer integer(number);
1084 return FormatInteger(parameters, integer, buffer, bufferSize, positions,
1085 positionCount, fieldCount, allFieldPositions);
1088 // FormatFloat
1089 status_t
1090 BGenericNumberFormat::FormatFloat(const BFloatFormatParameters *parameters,
1091 double number, BString *buffer, format_field_position *positions,
1092 int32 positionCount, int32 *fieldCount, bool allFieldPositions) const
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.
1105 return error;
1108 // FormatFloat
1109 status_t
1110 BGenericNumberFormat::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
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;
1165 // SetDefaultIntegerFormatParameters
1166 status_t
1167 BGenericNumberFormat::SetDefaultIntegerFormatParameters(
1168 const BIntegerFormatParameters *parameters)
1170 if (!parameters)
1171 return B_BAD_VALUE;
1172 fIntegerParameters = *parameters;
1173 return B_OK;
1176 // DefaultIntegerFormatParameters
1177 BIntegerFormatParameters *
1178 BGenericNumberFormat::DefaultIntegerFormatParameters()
1180 return &fIntegerParameters;
1183 // DefaultIntegerFormatParameters
1184 const BIntegerFormatParameters *
1185 BGenericNumberFormat::DefaultIntegerFormatParameters() const
1187 return &fIntegerParameters;
1190 // SetDefaultFloatFormatParameters
1191 status_t
1192 BGenericNumberFormat::SetDefaultFloatFormatParameters(
1193 const BFloatFormatParameters *parameters)
1195 if (!parameters)
1196 return B_BAD_VALUE;
1197 fFloatParameters = *parameters;
1198 return B_OK;
1201 // DefaultFloatFormatParameters
1202 BFloatFormatParameters *
1203 BGenericNumberFormat::DefaultFloatFormatParameters()
1205 return &fFloatParameters;
1208 // DefaultFloatFormatParameters
1209 const BFloatFormatParameters *
1210 BGenericNumberFormat::DefaultFloatFormatParameters() const
1212 return &fFloatParameters;
1215 // SetDigitSymbols
1216 status_t
1217 BGenericNumberFormat::SetDigitSymbols(const char **digits)
1219 // check parameters
1220 if (digits) {
1221 for (int i = 0; i < 10; i++) {
1222 if (!digits[i])
1223 return B_BAD_VALUE;
1226 // unset old
1227 if (fDigitSymbols) {
1228 delete[] fDigitSymbols;
1229 fDigitSymbols = NULL;
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;
1244 return B_OK;
1247 // SetFractionSeparator
1248 status_t
1249 BGenericNumberFormat::SetFractionSeparator(const char *decimalSeparator)
1251 return _SetSymbol(&fFractionSeparator, decimalSeparator);
1254 // SetGroupingInfo
1255 status_t
1256 BGenericNumberFormat::SetGroupingInfo(const char **groupingSeparators,
1257 size_t separatorCount, size_t *groupingSizes, size_t sizeCount)
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;
1267 // unset old
1268 if (fGroupingInfo) {
1269 delete fGroupingInfo;
1270 fGroupingInfo = NULL;
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;
1286 return B_OK;
1289 // SetExponentSymbol
1290 status_t
1291 BGenericNumberFormat::SetExponentSymbol(const char *exponentSymbol,
1292 const char *upperCaseExponentSymbol)
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;
1302 // SetSpecialNumberSymbols
1303 status_t
1304 BGenericNumberFormat::SetSpecialNumberSymbols(const char *nan,
1305 const char *infinity, const char *negativeInfinity,
1306 const char *upperCaseNaN, const char *upperCaseInfinity,
1307 const char *upperCaseNegativeInfinity)
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);
1322 if (error != B_OK)
1323 SetSpecialNumberSymbols(NULL, NULL, NULL, NULL, NULL, NULL);
1324 return error;
1327 // SetSignSymbols
1328 status_t
1329 BGenericNumberFormat::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)
1335 if (!fSignSymbols) {
1336 fSignSymbols = new(nothrow) SignSymbols;
1337 if (!fSignSymbols)
1338 return B_NO_MEMORY;
1340 return fSignSymbols->SetTo(plusPrefix, minusPrefix, padPlusPrefix,
1341 noForcePlusPrefix, plusSuffix, minusSuffix, padPlusSuffix,
1342 noForcePlusSuffix);
1345 // SetMantissaSignSymbols
1346 status_t
1347 BGenericNumberFormat::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)
1353 if (!fMantissaSignSymbols) {
1354 fMantissaSignSymbols = new(nothrow) SignSymbols;
1355 if (!fMantissaSignSymbols)
1356 return B_NO_MEMORY;
1358 return fMantissaSignSymbols->SetTo(plusPrefix, minusPrefix, padPlusPrefix,
1359 noForcePlusPrefix, plusSuffix, minusSuffix, padPlusSuffix,
1360 noForcePlusSuffix);
1363 // SetExponentSignSymbols
1364 status_t
1365 BGenericNumberFormat::SetExponentSignSymbols(const char *plusPrefix,
1366 const char *minusPrefix, const char *plusSuffix, const char *minusSuffix)
1368 if (!fExponentSignSymbols) {
1369 fExponentSignSymbols = new(nothrow) SignSymbols;
1370 if (!fExponentSignSymbols)
1371 return B_NO_MEMORY;
1373 return fExponentSignSymbols->SetTo(plusPrefix, minusPrefix, plusPrefix,
1374 plusPrefix, plusSuffix, minusSuffix, plusSuffix, plusSuffix);
1377 // FormatInteger
1378 status_t
1379 BGenericNumberFormat::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
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;
1420 // DigitSymbols
1421 const BGenericNumberFormat::Symbol *
1422 BGenericNumberFormat::DigitSymbols() const
1424 return (fDigitSymbols ? fDigitSymbols : kDefaultDigitSymbols);
1427 // FractionSeparator
1428 const BGenericNumberFormat::Symbol *
1429 BGenericNumberFormat::FractionSeparator() const
1431 return (fFractionSeparator ? fFractionSeparator
1432 : &kDefaultFractionSeparator);
1435 // GetGroupingInfo
1436 const BGenericNumberFormat::GroupingInfo *
1437 BGenericNumberFormat::GetGroupingInfo() const
1439 return (fGroupingInfo ? fGroupingInfo : &kDefaultGroupingInfo);
1442 // ExponentSymbol
1443 const BGenericNumberFormat::Symbol *
1444 BGenericNumberFormat::ExponentSymbol(bool upperCase) const
1446 if (fExponentSymbol) {
1447 return (upperCase && fUpperCaseExponentSymbol ? fUpperCaseExponentSymbol
1448 : fExponentSymbol);
1450 return (upperCase ? &kDefaultUpperCaseExponentSymbol
1451 : &kDefaultExponentSymbol);
1454 // NaNSymbol
1455 const BGenericNumberFormat::Symbol *
1456 BGenericNumberFormat::NaNSymbol(bool upperCase) const
1458 if (fNaNSymbol) {
1459 return (upperCase && fUpperCaseNaNSymbol ? fUpperCaseNaNSymbol
1460 : fNaNSymbol);
1462 return (upperCase ? &kDefaultUpperCaseNaNSymbol
1463 : &kDefaultNaNSymbol);
1466 // InfinitySymbol
1467 const BGenericNumberFormat::Symbol *
1468 BGenericNumberFormat::InfinitySymbol(bool upperCase) const
1470 if (fInfinitySymbol) {
1471 return (upperCase && fUpperCaseInfinitySymbol ? fUpperCaseInfinitySymbol
1472 : fInfinitySymbol);
1474 return (upperCase ? &kDefaultUpperCaseInfinitySymbol
1475 : &kDefaultInfinitySymbol);
1478 // NegativeInfinitySymbol
1479 const BGenericNumberFormat::Symbol *
1480 BGenericNumberFormat::NegativeInfinitySymbol(bool upperCase) const
1482 if (fNegativeInfinitySymbol) {
1483 return (upperCase && fUpperCaseNegativeInfinitySymbol
1484 ? fUpperCaseNegativeInfinitySymbol : fNegativeInfinitySymbol);
1486 return (upperCase ? &kDefaultUpperCaseNegativeInfinitySymbol
1487 : &kDefaultNegativeInfinitySymbol);
1490 // GetSpecialNumberSymbols
1491 void
1492 BGenericNumberFormat::GetSpecialNumberSymbols(bool upperCase,
1493 SpecialNumberSymbols *symbols) const
1495 symbols->nan = NaNSymbol(upperCase);
1496 symbols->infinity = InfinitySymbol(upperCase);
1497 symbols->negative_infinity = NegativeInfinitySymbol(upperCase);
1500 // GetSignSymbols
1501 const BGenericNumberFormat::SignSymbols *
1502 BGenericNumberFormat::GetSignSymbols() const
1504 return (fSignSymbols ? fSignSymbols : &kDefaultSignSymbols);
1507 // MantissaSignSymbols
1508 const BGenericNumberFormat::SignSymbols *
1509 BGenericNumberFormat::MantissaSignSymbols() const
1511 return (fMantissaSignSymbols ? fMantissaSignSymbols
1512 : &kDefaultMantissaSignSymbols);
1515 // ExponentSignSymbols
1516 const BGenericNumberFormat::SignSymbols *
1517 BGenericNumberFormat::ExponentSignSymbols() const
1519 return (fExponentSignSymbols ? fExponentSignSymbols
1520 : &kDefaultExponentSignSymbols);
1523 // _SetSymbol
1524 status_t
1525 BGenericNumberFormat::_SetSymbol(Symbol **symbol, const char *str)
1527 if (!str) {
1528 // no symbol -- unset old
1529 if (*symbol) {
1530 delete *symbol;
1531 symbol = NULL;
1533 } else {
1534 // allocate if not existing
1535 if (!*symbol) {
1536 *symbol = new(nothrow) Symbol;
1537 if (!*symbol)
1538 return B_NO_MEMORY;
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;
1548 return B_OK;