headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / libroot / add-ons / icu / ICULocaleBackend.cpp
blob21538c6d10b0438f2c86bd2cf85cb4552686556d
1 /*
2 * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "ICULocaleBackend.h"
9 #include <new>
11 #include <langinfo.h>
12 #include <locale.h>
13 #include <string.h>
14 #include <strings.h>
16 #include <ErrnoMaintainer.h>
19 namespace BPrivate {
20 namespace Libroot {
23 extern "C" LocaleBackend*
24 CreateInstance()
26 return new(std::nothrow) ICULocaleBackend();
30 ICULocaleBackend::ICULocaleBackend()
32 fThreadLocalStorageKey(_CreateThreadLocalStorageKey()),
33 fCollateData(fThreadLocalStorageKey),
34 fCtypeData(fThreadLocalStorageKey),
35 fMessagesData(fThreadLocalStorageKey),
36 fMonetaryData(fThreadLocalStorageKey, fLocaleConv),
37 fNumericData(fThreadLocalStorageKey, fLocaleConv),
38 fTimeData(fThreadLocalStorageKey, fLCTimeInfo, fMessagesData),
39 fTimeConversion(fTimeData)
44 ICULocaleBackend::~ICULocaleBackend()
46 pthread_key_delete(fThreadLocalStorageKey);
50 void
51 ICULocaleBackend::Initialize(LocaleDataBridge* dataBridge)
53 ErrnoMaintainer errnoMaintainer;
55 fCtypeData.Initialize(&dataBridge->ctypeDataBridge);
56 fMessagesData.Initialize(&dataBridge->messagesDataBridge);
57 fMonetaryData.Initialize(&dataBridge->monetaryDataBridge);
58 fNumericData.Initialize(&dataBridge->numericDataBridge);
59 fTimeData.Initialize(&dataBridge->timeDataBridge);
60 fTimeConversion.Initialize(&dataBridge->timeConversionDataBridge);
62 fPosixLanginfo = dataBridge->posixLanginfo;
64 _SetPosixLocale(LC_ALL);
68 const char*
69 ICULocaleBackend::SetLocale(int category, const char* posixLocaleName)
71 ErrnoMaintainer errnoMaintainer;
73 if (posixLocaleName == NULL)
74 return _QueryLocale(category);
76 if (strcasecmp(posixLocaleName, "POSIX") == 0
77 || strcasecmp(posixLocaleName, "C") == 0)
78 return _SetPosixLocale(category);
80 Locale locale = Locale::createCanonical(posixLocaleName);
81 switch (category) {
82 case LC_ALL:
83 if (fCollateData.SetTo(locale, posixLocaleName) != B_OK
84 || fCtypeData.SetTo(locale, posixLocaleName) != B_OK
85 || fMessagesData.SetTo(locale, posixLocaleName) != B_OK
86 || fMonetaryData.SetTo(locale, posixLocaleName) != B_OK
87 || fNumericData.SetTo(locale, posixLocaleName) != B_OK
88 || fTimeData.SetTo(locale, posixLocaleName) != B_OK)
89 return NULL;
90 break;
91 case LC_COLLATE:
92 if (fCollateData.SetTo(locale, posixLocaleName) != B_OK)
93 return NULL;
94 break;
95 case LC_CTYPE:
96 if (fCtypeData.SetTo(locale, posixLocaleName) != B_OK)
97 return NULL;
98 break;
99 case LC_MESSAGES:
100 if (fMessagesData.SetTo(locale, posixLocaleName) != B_OK)
101 return NULL;
102 break;
103 case LC_MONETARY:
104 if (fMonetaryData.SetTo(locale, posixLocaleName) != B_OK)
105 return NULL;
106 break;
107 case LC_NUMERIC:
108 if (fNumericData.SetTo(locale, posixLocaleName) != B_OK)
109 return NULL;
110 break;
111 case LC_TIME:
112 if (fTimeData.SetTo(locale, posixLocaleName) != B_OK)
113 return NULL;
114 break;
115 default:
116 // unsupported category
117 return NULL;
120 return posixLocaleName;
124 const struct lconv*
125 ICULocaleBackend::LocaleConv()
127 return &fLocaleConv;
131 const struct lc_time_t*
132 ICULocaleBackend::LCTimeInfo()
134 return &fLCTimeInfo;
139 ICULocaleBackend::IsWCType(wint_t wc, wctype_t charClass)
141 ErrnoMaintainer errnoMaintainer;
143 return fCtypeData.IsWCType(wc, charClass);
147 status_t
148 ICULocaleBackend::ToWCTrans(wint_t wc, wctrans_t transition, wint_t& result)
150 ErrnoMaintainer errnoMaintainer;
152 return fCtypeData.ToWCTrans(wc, transition, result);
156 status_t
157 ICULocaleBackend::MultibyteToWchar(wchar_t* wcOut, const char* mb,
158 size_t mbLength, mbstate_t* mbState, size_t& lengthOut)
160 ErrnoMaintainer errnoMaintainer;
162 return fCtypeData.MultibyteToWchar(wcOut, mb, mbLength, mbState, lengthOut);
166 status_t
167 ICULocaleBackend::MultibyteStringToWchar(wchar_t* wcDest, size_t wcDestLength,
168 const char** mbSource, size_t mbSourceLength, mbstate_t* mbState,
169 size_t& lengthOut)
171 ErrnoMaintainer errnoMaintainer;
173 return fCtypeData.MultibyteStringToWchar(wcDest, wcDestLength, mbSource,
174 mbSourceLength, mbState, lengthOut);
178 status_t
179 ICULocaleBackend::WcharToMultibyte(char* mbOut, wchar_t wc, mbstate_t* mbState,
180 size_t& lengthOut)
182 ErrnoMaintainer errnoMaintainer;
184 return fCtypeData.WcharToMultibyte(mbOut, wc, mbState, lengthOut);
188 status_t
189 ICULocaleBackend::WcharStringToMultibyte(char* mbDest, size_t mbDestLength,
190 const wchar_t** wcSource, size_t wcSourceLength, mbstate_t* mbState,
191 size_t& lengthOut)
193 ErrnoMaintainer errnoMaintainer;
195 return fCtypeData.WcharStringToMultibyte(mbDest, mbDestLength, wcSource,
196 wcSourceLength, mbState, lengthOut);
200 const char*
201 ICULocaleBackend::GetLanginfo(int index)
203 ErrnoMaintainer errnoMaintainer;
205 switch(index) {
206 case CODESET:
207 return fCtypeData.GetLanginfo(index);
209 case D_T_FMT:
210 case D_FMT:
211 case T_FMT:
212 case T_FMT_AMPM:
213 case AM_STR:
214 case PM_STR:
215 case DAY_1:
216 case DAY_2:
217 case DAY_3:
218 case DAY_4:
219 case DAY_5:
220 case DAY_6:
221 case DAY_7:
222 case ABDAY_1:
223 case ABDAY_2:
224 case ABDAY_3:
225 case ABDAY_4:
226 case ABDAY_5:
227 case ABDAY_6:
228 case ABDAY_7:
229 case MON_1:
230 case MON_2:
231 case MON_3:
232 case MON_4:
233 case MON_5:
234 case MON_6:
235 case MON_7:
236 case MON_8:
237 case MON_9:
238 case MON_10:
239 case MON_11:
240 case MON_12:
241 case ABMON_1:
242 case ABMON_2:
243 case ABMON_3:
244 case ABMON_4:
245 case ABMON_5:
246 case ABMON_6:
247 case ABMON_7:
248 case ABMON_8:
249 case ABMON_9:
250 case ABMON_10:
251 case ABMON_11:
252 case ABMON_12:
253 return fTimeData.GetLanginfo(index);
255 case ERA:
256 case ERA_D_FMT:
257 case ERA_D_T_FMT:
258 case ERA_T_FMT:
259 case ALT_DIGITS:
260 return fPosixLanginfo[index];
262 case RADIXCHAR:
263 case THOUSEP:
264 return fNumericData.GetLanginfo(index);
266 case YESEXPR:
267 case NOEXPR:
268 return fMessagesData.GetLanginfo(index);
270 case CRNCYSTR:
271 return fMonetaryData.GetLanginfo(index);
273 default:
274 return "";
279 status_t
280 ICULocaleBackend::Strcoll(const char* a, const char* b, int& result)
282 ErrnoMaintainer errnoMaintainer;
284 return fCollateData.Strcoll(a, b, result);
288 status_t
289 ICULocaleBackend::Strxfrm(char* out, const char* in, size_t size,
290 size_t& outSize)
292 ErrnoMaintainer errnoMaintainer;
294 return fCollateData.Strxfrm(out, in, size, outSize);
298 status_t
299 ICULocaleBackend::Wcscoll(const wchar_t* a, const wchar_t* b, int& result)
301 ErrnoMaintainer errnoMaintainer;
303 return fCollateData.Wcscoll(a, b, result);
307 status_t
308 ICULocaleBackend::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t size,
309 size_t& outSize)
311 ErrnoMaintainer errnoMaintainer;
313 return fCollateData.Wcsxfrm(out, in, size, outSize);
317 status_t
318 ICULocaleBackend::TZSet(const char* timeZoneID, const char* tz)
320 ErrnoMaintainer errnoMaintainer;
322 return fTimeConversion.TZSet(timeZoneID, tz);
326 status_t
327 ICULocaleBackend::Localtime(const time_t* inTime, struct tm* tmOut)
329 ErrnoMaintainer errnoMaintainer;
331 return fTimeConversion.Localtime(inTime, tmOut);
335 status_t
336 ICULocaleBackend::Gmtime(const time_t* inTime, struct tm* tmOut)
338 ErrnoMaintainer errnoMaintainer;
340 return fTimeConversion.Gmtime(inTime, tmOut);
344 status_t
345 ICULocaleBackend::Mktime(struct tm* inOutTm, time_t& timeOut)
347 ErrnoMaintainer errnoMaintainer;
349 return fTimeConversion.Mktime(inOutTm, timeOut);
353 const char*
354 ICULocaleBackend::_QueryLocale(int category)
356 switch (category) {
357 case LC_ALL:
359 // if all categories have the same locale, return that
360 const char* locale = fCollateData.PosixLocaleName();
361 if (strcmp(locale, fCtypeData.PosixLocaleName()) == 0
362 && strcmp(locale, fMessagesData.PosixLocaleName()) == 0
363 && strcmp(locale, fMonetaryData.PosixLocaleName()) == 0
364 && strcmp(locale, fNumericData.PosixLocaleName()) == 0
365 && strcmp(locale, fTimeData.PosixLocaleName()) == 0)
366 return locale;
368 // build a string with all info (at least glibc does it, too)
369 snprintf(fLocaleDescription, sizeof(fLocaleDescription),
370 "LC_COLLATE=%s;LC_CTYPE=%s;LC_MESSAGES=%s;LC_MONETARY=%s;"
371 "LC_NUMERIC=%s;LC_TIME=%s",
372 fCollateData.PosixLocaleName(), fCtypeData.PosixLocaleName(),
373 fMessagesData.PosixLocaleName(),
374 fMonetaryData.PosixLocaleName(), fNumericData.PosixLocaleName(),
375 fTimeData.PosixLocaleName());
376 return fLocaleDescription;
378 case LC_COLLATE:
379 return fCollateData.PosixLocaleName();
380 case LC_CTYPE:
381 return fCtypeData.PosixLocaleName();
382 case LC_MESSAGES:
383 return fMessagesData.PosixLocaleName();
384 case LC_MONETARY:
385 return fMonetaryData.PosixLocaleName();
386 case LC_NUMERIC:
387 return fNumericData.PosixLocaleName();
388 case LC_TIME:
389 return fTimeData.PosixLocaleName();
390 default:
391 // unsupported category
392 return NULL;
397 const char*
398 ICULocaleBackend::_SetPosixLocale(int category)
400 switch (category) {
401 case LC_ALL:
402 if (fCollateData.SetToPosix() != B_OK
403 || fCtypeData.SetToPosix() != B_OK
404 || fMessagesData.SetToPosix() != B_OK
405 || fMonetaryData.SetToPosix() != B_OK
406 || fNumericData.SetToPosix() != B_OK
407 || fTimeData.SetToPosix() != B_OK)
408 return NULL;
409 break;
410 case LC_COLLATE:
411 if (fCollateData.SetToPosix() != B_OK)
412 return NULL;
413 break;
414 case LC_CTYPE:
415 if (fCtypeData.SetToPosix() != B_OK)
416 return NULL;
417 break;
418 case LC_MESSAGES:
419 if (fMessagesData.SetToPosix() != B_OK)
420 return NULL;
421 break;
422 case LC_MONETARY:
423 if (fMonetaryData.SetToPosix() != B_OK)
424 return NULL;
425 break;
426 case LC_NUMERIC:
427 if (fNumericData.SetToPosix() != B_OK)
428 return NULL;
429 break;
430 case LC_TIME:
431 if (fTimeData.SetToPosix() != B_OK)
432 return NULL;
433 break;
434 default:
435 // unsupported category
436 return NULL;
439 return "POSIX";
443 pthread_key_t
444 ICULocaleBackend::_CreateThreadLocalStorageKey()
446 pthread_key_t key;
448 pthread_key_create(&key, ICULocaleBackend::_DestroyThreadLocalStorageValue);
450 return key;
454 void
455 ICULocaleBackend::_DestroyThreadLocalStorageValue(void* value)
457 ICUThreadLocalStorageValue* tlsValue
458 = static_cast<ICUThreadLocalStorageValue*>(value);
460 delete tlsValue;
464 } // namespace Libroot
465 } // namespace BPrivate