tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }