xref: /haiku/src/system/libroot/add-ons/icu/ICUCategoryData.cpp (revision 72156a402f54ea4be9dc3e3e9704c612f7d9ad16)
1 /*
2  * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "ICUCategoryData.h"
8 
9 #include <string.h>
10 
11 #include <unicode/uchar.h>
12 
13 
14 namespace BPrivate {
15 namespace Libroot {
16 
17 
18 ICUCategoryData::ICUCategoryData()
19 	:
20 	fConverter(NULL)
21 {
22 	*fPosixLocaleName = '\0';
23 	*fGivenCharset = '\0';
24 }
25 
26 
27 ICUCategoryData::~ICUCategoryData()
28 {
29 	if (fConverter)
30 		ucnv_close(fConverter);
31 }
32 
33 
34 status_t
35 ICUCategoryData::_SetupConverter()
36 {
37 	if (fConverter != NULL) {
38 		ucnv_close(fConverter);
39 		fConverter = NULL;
40 	}
41 
42 	UErrorCode icuStatus = U_ZERO_ERROR;
43 	fConverter = ucnv_open(fGivenCharset, &icuStatus);
44 	if (fConverter == NULL)
45 		return B_NAME_NOT_FOUND;
46 
47 	icuStatus = U_ZERO_ERROR;
48 	ucnv_setToUCallBack(fConverter, UCNV_TO_U_CALLBACK_STOP, NULL, NULL,
49 		NULL, &icuStatus);
50 	icuStatus = U_ZERO_ERROR;
51 	ucnv_setFromUCallBack(fConverter, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL,
52 		NULL, &icuStatus);
53 	if (!U_SUCCESS(icuStatus))
54 		return B_ERROR;
55 
56 	return B_OK;
57 }
58 
59 
60 status_t
61 ICUCategoryData::SetTo(const Locale& locale, const char* posixLocaleName)
62 {
63 	if (!posixLocaleName)
64 		return B_BAD_VALUE;
65 
66 	fLocale = locale;
67 	strlcpy(fPosixLocaleName, posixLocaleName, skMaxPosixLocaleNameLen);
68 	*fGivenCharset = '\0';
69 
70 	// POSIX locales often contain an embedded charset, but ICU does not
71 	// handle these within locales (that part of the name is simply
72 	// ignored).
73 	// We need to fetch the charset specification and lookup an appropriate
74 	// ICU charset converter. This converter will later be used to get info
75 	// about ctype properties.
76 	const char* charsetStart = strchr(fPosixLocaleName, '.');
77 	if (charsetStart) {
78 		++charsetStart;
79 		int l = 0;
80 		while (charsetStart[l] != '\0' && charsetStart[l] != '@')
81 			++l;
82 		snprintf(fGivenCharset, UCNV_MAX_CONVERTER_NAME_LENGTH, "%.*s", l,
83 			charsetStart);
84 	}
85 	if (!strlen(fGivenCharset))
86 		strcpy(fGivenCharset, "utf-8");
87 
88 	return _SetupConverter();
89 }
90 
91 
92 status_t
93 ICUCategoryData::SetToPosix()
94 {
95 	fLocale = Locale::createFromName("en_US_POSIX");
96 	strcpy(fPosixLocaleName, "POSIX");
97 	strcpy(fGivenCharset, "US-ASCII");
98 
99 	return _SetupConverter();
100 }
101 
102 
103 status_t
104 ICUCategoryData::_ConvertUnicodeStringToLocaleconvEntry(
105 	const UnicodeString& string, char* destination, int destinationSize,
106 	const char* defaultValue)
107 {
108 	status_t result = B_OK;
109 	UErrorCode icuStatus = U_ZERO_ERROR;
110 
111 	ucnv_fromUChars(fConverter, destination, destinationSize,
112 		string.getBuffer(), string.length(), &icuStatus);
113 	if (!U_SUCCESS(icuStatus)) {
114 		switch (icuStatus) {
115 			case U_BUFFER_OVERFLOW_ERROR:
116 				result = B_NAME_TOO_LONG;
117 				break;
118 			case U_INVALID_CHAR_FOUND:
119 			case U_TRUNCATED_CHAR_FOUND:
120 			case U_ILLEGAL_CHAR_FOUND:
121 				result = B_BAD_DATA;
122 				break;
123 			default:
124 				result = B_ERROR;
125 				break;
126 		}
127 		strlcpy(destination, defaultValue, destinationSize);
128 	}
129 
130 	return result;
131 }
132 
133 
134 }	// namespace Libroot
135 }	// namespace BPrivate
136