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