ulocbuilder.cpp (4836B)
1 // © 2023 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 4 #include <utility> 5 6 #include "unicode/bytestream.h" 7 #include "unicode/localebuilder.h" 8 #include "unicode/locid.h" 9 #include "unicode/stringpiece.h" 10 #include "unicode/umachine.h" 11 #include "unicode/ulocbuilder.h" 12 #include "bytesinkutil.h" 13 #include "cstring.h" 14 #include "ustr_imp.h" 15 16 using icu::StringPiece; 17 18 #define EXTERNAL(i) (reinterpret_cast<ULocaleBuilder*>(i)) 19 #define INTERNAL(e) (reinterpret_cast<icu::LocaleBuilder*>(e)) 20 #define CONST_INTERNAL(e) (reinterpret_cast<const icu::LocaleBuilder*>(e)) 21 22 ULocaleBuilder* ulocbld_open() { 23 return EXTERNAL(new icu::LocaleBuilder()); 24 } 25 26 void ulocbld_close(ULocaleBuilder* builder) { 27 if (builder == nullptr) return; 28 delete INTERNAL(builder); 29 } 30 31 void ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t length) { 32 if (builder == nullptr) return; 33 icu::Locale l; 34 if (length < 0 || locale[length] == '\0') { 35 l = icu::Locale(locale); 36 } else { 37 if (length >= ULOC_FULLNAME_CAPACITY) { 38 l.setToBogus(); 39 } else { 40 // locale is not null termined but Locale API require one. 41 // Create a null termined version in buf. 42 char buf[ULOC_FULLNAME_CAPACITY]; 43 uprv_memcpy(buf, locale, length); 44 buf[length] = '\0'; 45 l = icu::Locale(buf); 46 } 47 } 48 INTERNAL(builder)->setLocale(l); 49 } 50 51 void 52 ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale) { 53 if (builder == nullptr) return; 54 INTERNAL(builder)->setLocale(*(reinterpret_cast<const icu::Locale*>(locale))); 55 ulocale_close(locale); 56 } 57 58 #define STRING_PIECE(s, l) ((l)<0 ? StringPiece(s) : StringPiece((s), (l))) 59 60 #define IMPL_ULOCBLD_SETTER(N) \ 61 void ulocbld_##N(ULocaleBuilder* bld, const char* s, int32_t l) { \ 62 if (bld == nullptr) return; \ 63 INTERNAL(bld)->N(STRING_PIECE(s,l)); \ 64 } 65 66 IMPL_ULOCBLD_SETTER(setLanguageTag) 67 IMPL_ULOCBLD_SETTER(setLanguage) 68 IMPL_ULOCBLD_SETTER(setScript) 69 IMPL_ULOCBLD_SETTER(setRegion) 70 IMPL_ULOCBLD_SETTER(setVariant) 71 IMPL_ULOCBLD_SETTER(addUnicodeLocaleAttribute) 72 IMPL_ULOCBLD_SETTER(removeUnicodeLocaleAttribute) 73 74 void ulocbld_setExtension(ULocaleBuilder* builder, char key, const char* value, int32_t length) { 75 if (builder == nullptr) return; 76 INTERNAL(builder)->setExtension(key, STRING_PIECE(value, length)); 77 } 78 79 void ulocbld_setUnicodeLocaleKeyword( 80 ULocaleBuilder* builder, const char* key, int32_t keyLength, 81 const char* type, int32_t typeLength) { 82 if (builder == nullptr) return; 83 INTERNAL(builder)->setUnicodeLocaleKeyword( 84 STRING_PIECE(key, keyLength), STRING_PIECE(type, typeLength)); 85 } 86 87 void ulocbld_clear(ULocaleBuilder* builder) { 88 if (builder == nullptr) return; 89 INTERNAL(builder)->clear(); 90 } 91 92 void ulocbld_clearExtensions(ULocaleBuilder* builder) { 93 if (builder == nullptr) return; 94 INTERNAL(builder)->clearExtensions(); 95 } 96 97 98 ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err) { 99 if (builder == nullptr) { 100 *err = U_ILLEGAL_ARGUMENT_ERROR; 101 return nullptr; 102 } 103 icu::Locale l = INTERNAL(builder)->build(*err); 104 if (U_FAILURE(*err)) return nullptr; 105 icu::Locale* r = l.clone(); 106 if (r == nullptr) { 107 *err = U_MEMORY_ALLOCATION_ERROR; 108 return nullptr; 109 } 110 return reinterpret_cast<ULocale*>(r); 111 } 112 113 int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder, 114 char* buffer, int32_t bufferCapacity, UErrorCode* err) { 115 if (U_FAILURE(*err)) { return 0; } 116 if (builder == nullptr) { 117 *err = U_ILLEGAL_ARGUMENT_ERROR; 118 return 0; 119 } 120 icu::Locale l = INTERNAL(builder)->build(*err); 121 if (U_FAILURE(*err)) { return 0; } 122 int32_t length = static_cast<int32_t>(uprv_strlen(l.getName())); 123 if (0 < length && length <= bufferCapacity) { 124 uprv_memcpy(buffer, l.getName(), length); 125 } 126 return u_terminateChars(buffer, bufferCapacity, length, err); 127 } 128 129 int32_t ulocbld_buildLanguageTag(ULocaleBuilder* builder, 130 char* buffer, int32_t bufferCapacity, UErrorCode* err) { 131 if (U_FAILURE(*err)) { return 0; } 132 if (builder == nullptr) { 133 *err = U_ILLEGAL_ARGUMENT_ERROR; 134 return 0; 135 } 136 icu::Locale l = INTERNAL(builder)->build(*err); 137 return icu::ByteSinkUtil::viaByteSinkToTerminatedChars( 138 buffer, bufferCapacity, 139 [&](icu::ByteSink& sink, UErrorCode& status) { 140 l.toLanguageTag(sink, status); 141 }, 142 *err); 143 } 144 145 UBool ulocbld_copyErrorTo(const ULocaleBuilder* builder, UErrorCode *outErrorCode) { 146 if (builder == nullptr) { 147 *outErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 148 return true; 149 } 150 return CONST_INTERNAL(builder)->copyErrorTo(*outErrorCode); 151 }