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