1/*
2 * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "ICUNumericData.h"
8
9#include <langinfo.h>
10#include <locale.h>
11#include <strings.h>
12
13
14namespace BPrivate {
15namespace Libroot {
16
17
18ICUNumericData::ICUNumericData(pthread_key_t tlsKey, struct lconv& localeConv)
19	:
20	inherited(tlsKey),
21	fLocaleConv(localeConv),
22	fDataBridge(NULL)
23{
24	fLocaleConv.decimal_point = fDecimalPoint;
25	fLocaleConv.thousands_sep = fThousandsSep;
26	fLocaleConv.grouping = fGrouping;
27}
28
29
30void
31ICUNumericData::Initialize(LocaleNumericDataBridge* dataBridge)
32{
33	dataBridge->glibcNumericLocale.values[0].string = fDecimalPoint;
34	dataBridge->glibcNumericLocale.values[1].string = fThousandsSep;
35	dataBridge->glibcNumericLocale.values[2].string = fGrouping;
36	fDataBridge = dataBridge;
37}
38
39
40status_t
41ICUNumericData::SetTo(const Locale& locale, const char* posixLocaleName)
42{
43	status_t result = inherited::SetTo(locale, posixLocaleName);
44
45	if (result == B_OK) {
46		UErrorCode icuStatus = U_ZERO_ERROR;
47		DecimalFormat* numberFormat = dynamic_cast<DecimalFormat*>(
48			NumberFormat::createInstance(locale, UNUM_DECIMAL, icuStatus));
49		if (!U_SUCCESS(icuStatus))
50			return B_UNSUPPORTED;
51		if (!numberFormat)
52			return B_BAD_TYPE;
53		const DecimalFormatSymbols* formatSymbols
54			= numberFormat->getDecimalFormatSymbols();
55		if (!formatSymbols)
56			result = B_BAD_DATA;
57
58		if (result == B_OK) {
59			result = _SetLocaleconvEntry(formatSymbols, fDecimalPoint,
60				DecimalFormatSymbols::kDecimalSeparatorSymbol);
61			fDataBridge->glibcNumericLocale.values[3].word
62				= (unsigned int)fDecimalPoint[0];
63		}
64		if (result == B_OK) {
65			result = _SetLocaleconvEntry(formatSymbols, fThousandsSep,
66				DecimalFormatSymbols::kGroupingSeparatorSymbol);
67			fDataBridge->glibcNumericLocale.values[4].word
68				= (unsigned int)fThousandsSep[0];
69		}
70		if (result == B_OK) {
71			int32 groupingSize = numberFormat->getGroupingSize();
72			if (groupingSize < 1)
73				fGrouping[0] = '\0';
74			else {
75				fGrouping[0] = groupingSize;
76				int32 secondaryGroupingSize
77					= numberFormat->getSecondaryGroupingSize();
78				if (secondaryGroupingSize < 1)
79					fGrouping[1] = '\0';
80				else {
81					fGrouping[1] = secondaryGroupingSize;
82					fGrouping[2] = '\0';
83				}
84			}
85		}
86
87		delete numberFormat;
88	}
89
90	return result;
91}
92
93
94status_t
95ICUNumericData::SetToPosix()
96{
97	status_t result = inherited::SetToPosix();
98
99	if (result == B_OK) {
100		strcpy(fDecimalPoint, fDataBridge->posixLocaleConv->decimal_point);
101		strcpy(fThousandsSep, fDataBridge->posixLocaleConv->thousands_sep);
102		strcpy(fGrouping, fDataBridge->posixLocaleConv->grouping);
103		fDataBridge->glibcNumericLocale.values[3].word
104			= (unsigned int)fDecimalPoint[0];
105		fDataBridge->glibcNumericLocale.values[4].word
106			= (unsigned int)fThousandsSep[0];
107	}
108
109	return result;
110}
111
112
113const char*
114ICUNumericData::GetLanginfo(int index)
115{
116	switch(index) {
117		case RADIXCHAR:
118			return fDecimalPoint;
119		case THOUSEP:
120			return fThousandsSep;
121		default:
122			return "";
123	}
124}
125
126
127}	// namespace Libroot
128}	// namespace BPrivate
129