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