Update ICU to 75.1

This commit is contained in:
bruvzg 2024-05-14 11:41:19 +03:00
parent 557f63d037
commit e74fea2864
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
129 changed files with 8033 additions and 7861 deletions

View File

@ -285,7 +285,7 @@ License: HarfBuzz
Files: ./thirdparty/icu4c/ Files: ./thirdparty/icu4c/
Comment: International Components for Unicode Comment: International Components for Unicode
Copyright: 1991-2021, Unicode Copyright: 2016-2024, Unicode, Inc.
License: Unicode License: Unicode
Files: ./thirdparty/jpeg-compressor/ Files: ./thirdparty/jpeg-compressor/

View File

@ -468,7 +468,7 @@ if env["builtin_icu4c"]:
] ]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
icu_data_name = "icudt74l.dat" icu_data_name = "icudt75l.dat"
if env.editor_build: if env.editor_build:
env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name) env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name)

View File

@ -703,7 +703,7 @@ thirdparty_icu_sources = [
] ]
thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources] thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources]
icu_data_name = "icudt74l.dat" icu_data_name = "icudt75l.dat"
if env["static_icu_data"]: if env["static_icu_data"]:
env_icu.Depends("../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/" + icu_data_name) env_icu.Depends("../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/" + icu_data_name)

View File

@ -391,7 +391,7 @@ Files extracted from upstream source:
## icu4c ## icu4c
- Upstream: https://github.com/unicode-org/icu - Upstream: https://github.com/unicode-org/icu
- Version: 74.2 (2d029329c82c7792b985024b2bdab5fc7278fbc8, 2023) - Version: 75.1 (7750081bda4b3bc1768ae03849ec70f67ea10625, 2024)
- License: Unicode - License: Unicode
Files extracted from upstream source: Files extracted from upstream source:
@ -403,7 +403,7 @@ Files extracted from upstream source:
Files generated from upstream source: Files generated from upstream source:
- The `icudt74l.dat` built with the provided `godot_data.json` config file (see - The `icudt75l.dat` built with the provided `godot_data.json` config file (see
https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md
for instructions). for instructions).
@ -413,7 +413,7 @@ Files generated from upstream source:
3. Reconfigure ICU with custom data config: 3. Reconfigure ICU with custom data config:
`ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common` `ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common`
4. Delete `data/out` folder and rebuild data: `cd data && rm -rf ./out && make` 4. Delete `data/out` folder and rebuild data: `cd data && rm -rf ./out && make`
5. Copy `source/data/out/icudt74l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt74l.dat` 5. Copy `source/data/out/icudt75l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt75l.dat`
## jpeg-compressor ## jpeg-compressor

View File

@ -2,7 +2,7 @@ UNICODE LICENSE V3
COPYRIGHT AND PERMISSION NOTICE COPYRIGHT AND PERMISSION NOTICE
Copyright © 2016-2023 Unicode, Inc. Copyright © 2016-2024 Unicode, Inc.
NOTICE TO USER: Carefully read the following legal agreement. BY NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
@ -38,6 +38,8 @@ not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written dealings in these Data Files or Software without prior written
authorization of the copyright holder. authorization of the copyright holder.
SPDX-License-Identifier: Unicode-3.0
---------------------------------------------------------------------- ----------------------------------------------------------------------
Third-Party Software Licenses Third-Party Software Licenses

View File

@ -114,13 +114,11 @@ UnhandledEngine::handleCharacter(UChar32 c) {
*/ */
ICULanguageBreakFactory::ICULanguageBreakFactory(UErrorCode &/*status*/) { ICULanguageBreakFactory::ICULanguageBreakFactory(UErrorCode &/*status*/) {
fEngines = 0; fEngines = nullptr;
} }
ICULanguageBreakFactory::~ICULanguageBreakFactory() { ICULanguageBreakFactory::~ICULanguageBreakFactory() {
if (fEngines != 0) {
delete fEngines; delete fEngines;
}
} }
void ICULanguageBreakFactory::ensureEngines(UErrorCode& status) { void ICULanguageBreakFactory::ensureEngines(UErrorCode& status) {

View File

@ -438,17 +438,14 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status)
UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE); UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE);
uprv_strcpy(lb_lw, "line"); uprv_strcpy(lb_lw, "line");
UErrorCode kvStatus = U_ZERO_ERROR; UErrorCode kvStatus = U_ZERO_ERROR;
CharString value; auto value = loc.getKeywordValue<CharString>("lb", kvStatus);
CharStringByteSink valueSink(&value);
loc.getKeywordValue("lb", valueSink, kvStatus);
if (U_SUCCESS(kvStatus) && (value == "strict" || value == "normal" || value == "loose")) { if (U_SUCCESS(kvStatus) && (value == "strict" || value == "normal" || value == "loose")) {
uprv_strcat(lb_lw, "_"); uprv_strcat(lb_lw, "_");
uprv_strcat(lb_lw, value.data()); uprv_strcat(lb_lw, value.data());
} }
// lw=phrase is only supported in Japanese and Korean // lw=phrase is only supported in Japanese and Korean
if (uprv_strcmp(loc.getLanguage(), "ja") == 0 || uprv_strcmp(loc.getLanguage(), "ko") == 0) { if (uprv_strcmp(loc.getLanguage(), "ja") == 0 || uprv_strcmp(loc.getLanguage(), "ko") == 0) {
value.clear(); value = loc.getKeywordValue<CharString>("lw", kvStatus);
loc.getKeywordValue("lw", valueSink, kvStatus);
if (U_SUCCESS(kvStatus) && value == "phrase") { if (U_SUCCESS(kvStatus) && value == "phrase") {
uprv_strcat(lb_lw, "_"); uprv_strcat(lb_lw, "_");
uprv_strcat(lb_lw, value.data()); uprv_strcat(lb_lw, value.data());
@ -500,7 +497,7 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status)
Locale Locale
BreakIterator::getLocale(ULocDataLocaleType type, UErrorCode& status) const { BreakIterator::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
if (type == ULOC_REQUESTED_LOCALE) { if (type == ULOC_REQUESTED_LOCALE) {
return Locale(requestLocale); return {requestLocale};
} }
U_LOCALE_BASED(locBased, *this); U_LOCALE_BASED(locBased, *this);
return locBased.getLocale(type, status); return locBased.getLocale(type, status);

View File

@ -7,18 +7,52 @@
#ifndef BYTESINKUTIL_H #ifndef BYTESINKUTIL_H
#define BYTESINKUTIL_H #define BYTESINKUTIL_H
#include <type_traits>
#include "unicode/utypes.h" #include "unicode/utypes.h"
#include "unicode/bytestream.h" #include "unicode/bytestream.h"
#include "unicode/edits.h" #include "unicode/edits.h"
#include "charstr.h"
#include "cmemory.h" #include "cmemory.h"
#include "uassert.h" #include "uassert.h"
#include "ustr_imp.h"
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
class ByteSink; class ByteSink;
class CharString;
class Edits; class Edits;
class U_COMMON_API CharStringByteSink : public ByteSink {
public:
CharStringByteSink(CharString* dest);
~CharStringByteSink() override;
CharStringByteSink() = delete;
CharStringByteSink(const CharStringByteSink&) = delete;
CharStringByteSink& operator=(const CharStringByteSink&) = delete;
void Append(const char* bytes, int32_t n) override;
char* GetAppendBuffer(int32_t min_capacity,
int32_t desired_capacity_hint,
char* scratch,
int32_t scratch_capacity,
int32_t* result_capacity) override;
private:
CharString& dest_;
};
// CharString doesn't provide the public API that StringByteSink requires a
// string class to have so this template specialization replaces the default
// implementation of StringByteSink<CharString> with CharStringByteSink.
template<>
class StringByteSink<CharString> : public CharStringByteSink {
public:
StringByteSink(CharString* dest) : CharStringByteSink(dest) { }
StringByteSink(CharString* dest, int32_t /*initialAppendCapacity*/) : CharStringByteSink(dest) { }
};
class U_COMMON_API ByteSinkUtil { class U_COMMON_API ByteSinkUtil {
public: public:
ByteSinkUtil() = delete; // all static ByteSinkUtil() = delete; // all static
@ -57,32 +91,66 @@ public:
ByteSink &sink, uint32_t options, Edits *edits, ByteSink &sink, uint32_t options, Edits *edits,
UErrorCode &errorCode); UErrorCode &errorCode);
/**
* Calls a lambda that writes to a ByteSink with a CheckedArrayByteSink
* and then returns through u_terminateChars(), in order to implement
* the classic ICU4C C API writing to a fix sized buffer on top of a
* contemporary C++ API.
*
* @param buffer receiving buffer
* @param capacity capacity of receiving buffer
* @param lambda that gets called with the sink as an argument
* @param status set to U_BUFFER_OVERFLOW_ERROR on overflow
* @return number of bytes written, or needed (in case of overflow)
* @internal
*/
template <typename F,
typename = std::enable_if_t<
std::is_invocable_r_v<void, F, ByteSink&, UErrorCode&>>>
static int32_t viaByteSinkToTerminatedChars(char* buffer, int32_t capacity,
F&& lambda,
UErrorCode& status) {
if (U_FAILURE(status)) { return 0; }
CheckedArrayByteSink sink(buffer, capacity);
lambda(sink, status);
if (U_FAILURE(status)) { return 0; }
int32_t reslen = sink.NumberOfBytesAppended();
if (sink.Overflowed()) {
status = U_BUFFER_OVERFLOW_ERROR;
return reslen;
}
return u_terminateChars(buffer, capacity, reslen, &status);
}
/**
* Calls a lambda that writes to a ByteSink with a CharStringByteSink and
* then returns a CharString, in order to implement a contemporary C++ API
* on top of a C/C++ compatibility ByteSink API.
*
* @param lambda that gets called with the sink as an argument
* @param status to check and report
* @return the resulting string, or an empty string (in case of error)
* @internal
*/
template <typename F,
typename = std::enable_if_t<
std::is_invocable_r_v<void, F, ByteSink&, UErrorCode&>>>
static CharString viaByteSinkToCharString(F&& lambda, UErrorCode& status) {
if (U_FAILURE(status)) { return {}; }
CharString result;
CharStringByteSink sink(&result);
lambda(sink, status);
return result;
}
private: private:
static void appendNonEmptyUnchanged(const uint8_t *s, int32_t length, static void appendNonEmptyUnchanged(const uint8_t *s, int32_t length,
ByteSink &sink, uint32_t options, Edits *edits); ByteSink &sink, uint32_t options, Edits *edits);
}; };
class U_COMMON_API CharStringByteSink : public ByteSink {
public:
CharStringByteSink(CharString* dest);
~CharStringByteSink() override;
CharStringByteSink() = delete;
CharStringByteSink(const CharStringByteSink&) = delete;
CharStringByteSink& operator=(const CharStringByteSink&) = delete;
void Append(const char* bytes, int32_t n) override;
char* GetAppendBuffer(int32_t min_capacity,
int32_t desired_capacity_hint,
char* scratch,
int32_t scratch_capacity,
int32_t* result_capacity) override;
private:
CharString& dest_;
};
U_NAMESPACE_END U_NAMESPACE_END
#endif //BYTESINKUTIL_H #endif //BYTESINKUTIL_H

View File

@ -64,6 +64,7 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CanonicalIterator) UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CanonicalIterator)
/** /**
*@param source string to get results for *@param source string to get results for
*/ */
@ -73,10 +74,10 @@ CanonicalIterator::CanonicalIterator(const UnicodeString &sourceStr, UErrorCode
pieces_lengths(nullptr), pieces_lengths(nullptr),
current(nullptr), current(nullptr),
current_length(0), current_length(0),
nfd(*Normalizer2::getNFDInstance(status)), nfd(Normalizer2::getNFDInstance(status)),
nfcImpl(*Normalizer2Factory::getNFCImpl(status)) nfcImpl(Normalizer2Factory::getNFCImpl(status))
{ {
if(U_SUCCESS(status) && nfcImpl.ensureCanonIterData(status)) { if(U_SUCCESS(status) && nfcImpl->ensureCanonIterData(status)) {
setSource(sourceStr, status); setSource(sourceStr, status);
} }
} }
@ -172,7 +173,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
int32_t i = 0; int32_t i = 0;
UnicodeString *list = nullptr; UnicodeString *list = nullptr;
nfd.normalize(newSource, source, status); nfd->normalize(newSource, source, status);
if(U_FAILURE(status)) { if(U_FAILURE(status)) {
return; return;
} }
@ -194,7 +195,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
current[0] = 0; current[0] = 0;
pieces[0] = new UnicodeString[1]; pieces[0] = new UnicodeString[1];
pieces_lengths[0] = 1; pieces_lengths[0] = 1;
if (pieces[0] == 0) { if (pieces[0] == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
goto CleanPartialInitialization; goto CleanPartialInitialization;
} }
@ -203,7 +204,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
list = new UnicodeString[source.length()]; list = new UnicodeString[source.length()];
if (list == 0) { if (list == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
goto CleanPartialInitialization; goto CleanPartialInitialization;
} }
@ -219,7 +220,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
// on the NFD form - see above). // on the NFD form - see above).
for (; i < source.length(); i += U16_LENGTH(cp)) { for (; i < source.length(); i += U16_LENGTH(cp)) {
cp = source.char32At(i); cp = source.char32At(i);
if (nfcImpl.isCanonSegmentStarter(cp)) { if (nfcImpl->isCanonSegmentStarter(cp)) {
source.extract(start, i-start, list[list_length++]); // add up to i source.extract(start, i-start, list[list_length++]); // add up to i
start = i; start = i;
} }
@ -252,9 +253,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
return; return;
// Common section to cleanup all local variables and reset object variables. // Common section to cleanup all local variables and reset object variables.
CleanPartialInitialization: CleanPartialInitialization:
if (list != nullptr) {
delete[] list; delete[] list;
}
cleanPieces(); cleanPieces();
} }
@ -264,10 +263,19 @@ CleanPartialInitialization:
* @param source the string to find permutations for * @param source the string to find permutations for
* @return the results in a set. * @return the results in a set.
*/ */
void U_EXPORT2 CanonicalIterator::permute(UnicodeString &source, UBool skipZeros, Hashtable *result, UErrorCode &status) { void U_EXPORT2 CanonicalIterator::permute(UnicodeString &source, UBool skipZeros, Hashtable *result, UErrorCode &status, int32_t depth) {
if(U_FAILURE(status)) { if(U_FAILURE(status)) {
return; return;
} }
// To avoid infinity loop caused by permute, we limit the depth of recursive
// call to permute and return U_UNSUPPORTED_ERROR.
// We know in some unit test we need at least 4. Set to 8 just in case some
// unforseen use cases.
constexpr int32_t kPermuteDepthLimit = 8;
if (depth > kPermuteDepthLimit) {
status = U_UNSUPPORTED_ERROR;
return;
}
//if (PROGRESS) printf("Permute: %s\n", UToS(Tr(source))); //if (PROGRESS) printf("Permute: %s\n", UToS(Tr(source)));
int32_t i = 0; int32_t i = 0;
@ -277,7 +285,7 @@ void U_EXPORT2 CanonicalIterator::permute(UnicodeString &source, UBool skipZeros
if (source.length() <= 2 && source.countChar32() <= 1) { if (source.length() <= 2 && source.countChar32() <= 1) {
UnicodeString *toPut = new UnicodeString(source); UnicodeString *toPut = new UnicodeString(source);
/* test for nullptr */ /* test for nullptr */
if (toPut == 0) { if (toPut == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
return; return;
} }
@ -311,7 +319,7 @@ void U_EXPORT2 CanonicalIterator::permute(UnicodeString &source, UBool skipZeros
// see what the permutations of the characters before and after this one are // see what the permutations of the characters before and after this one are
//Hashtable *subpermute = permute(source.substring(0,i) + source.substring(i + UTF16.getCharCount(cp))); //Hashtable *subpermute = permute(source.substring(0,i) + source.substring(i + UTF16.getCharCount(cp)));
permute(subPermuteString.remove(i, U16_LENGTH(cp)), skipZeros, &subpermute, status); permute(subPermuteString.remove(i, U16_LENGTH(cp)), skipZeros, &subpermute, status, depth+1);
/* Test for buffer overflows */ /* Test for buffer overflows */
if(U_FAILURE(status)) { if(U_FAILURE(status)) {
return; return;
@ -346,7 +354,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i
Hashtable permutations(status); Hashtable permutations(status);
Hashtable basic(status); Hashtable basic(status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return 0; return nullptr;
} }
result.setValueDeleter(uprv_deleteUObject); result.setValueDeleter(uprv_deleteUObject);
permutations.setValueDeleter(uprv_deleteUObject); permutations.setValueDeleter(uprv_deleteUObject);
@ -381,7 +389,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i
//UnicodeString *possible = new UnicodeString(*((UnicodeString *)(ne2->value.pointer))); //UnicodeString *possible = new UnicodeString(*((UnicodeString *)(ne2->value.pointer)));
UnicodeString possible(*((UnicodeString *)(ne2->value.pointer))); UnicodeString possible(*((UnicodeString *)(ne2->value.pointer)));
UnicodeString attempt; UnicodeString attempt;
nfd.normalize(possible, attempt, status); nfd->normalize(possible, attempt, status);
// TODO: check if operator == is semanticaly the same as attempt.equals(segment) // TODO: check if operator == is semanticaly the same as attempt.equals(segment)
if (attempt==segment) { if (attempt==segment) {
@ -399,7 +407,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i
/* Test for buffer overflows */ /* Test for buffer overflows */
if(U_FAILURE(status)) { if(U_FAILURE(status)) {
return 0; return nullptr;
} }
// convert into a String[] to clean up storage // convert into a String[] to clean up storage
//String[] finalResult = new String[result.size()]; //String[] finalResult = new String[result.size()];
@ -407,7 +415,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i
int32_t resultCount; int32_t resultCount;
if((resultCount = result.count()) != 0) { if((resultCount = result.count()) != 0) {
finalResult = new UnicodeString[resultCount]; finalResult = new UnicodeString[resultCount];
if (finalResult == 0) { if (finalResult == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
return nullptr; return nullptr;
} }
@ -448,7 +456,7 @@ Hashtable *CanonicalIterator::getEquivalents2(Hashtable *fillinResult, const cha
for (int32_t i = 0; i < segLen; i += U16_LENGTH(cp)) { for (int32_t i = 0; i < segLen; i += U16_LENGTH(cp)) {
// see if any character is at the start of some decomposition // see if any character is at the start of some decomposition
U16_GET(segment, 0, i, segLen, cp); U16_GET(segment, 0, i, segLen, cp);
if (!nfcImpl.getCanonStartSet(cp, starts)) { if (!nfcImpl->getCanonStartSet(cp, starts)) {
continue; continue;
} }
// if so, see which decompositions match // if so, see which decompositions match
@ -471,7 +479,7 @@ Hashtable *CanonicalIterator::getEquivalents2(Hashtable *fillinResult, const cha
UnicodeString item = *((UnicodeString *)(ne->value.pointer)); UnicodeString item = *((UnicodeString *)(ne->value.pointer));
UnicodeString *toAdd = new UnicodeString(prefix); UnicodeString *toAdd = new UnicodeString(prefix);
/* test for nullptr */ /* test for nullptr */
if (toAdd == 0) { if (toAdd == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
return nullptr; return nullptr;
} }
@ -509,7 +517,7 @@ Hashtable *CanonicalIterator::extract(Hashtable *fillinResult, UChar32 comp, con
UnicodeString temp(comp); UnicodeString temp(comp);
int32_t inputLen=temp.length(); int32_t inputLen=temp.length();
UnicodeString decompString; UnicodeString decompString;
nfd.normalize(temp, decompString, status); nfd->normalize(temp, decompString, status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return nullptr; return nullptr;
} }
@ -573,7 +581,7 @@ Hashtable *CanonicalIterator::extract(Hashtable *fillinResult, UChar32 comp, con
// brute force approach // brute force approach
// check to make sure result is canonically equivalent // check to make sure result is canonically equivalent
UnicodeString trial; UnicodeString trial;
nfd.normalize(temp, trial, status); nfd->normalize(temp, trial, status);
if(U_FAILURE(status) || trial.compare(segment+segmentPos, segLen - segmentPos) != 0) { if(U_FAILURE(status) || trial.compare(segment+segmentPos, segLen - segmentPos) != 0) {
return nullptr; return nullptr;
} }

View File

@ -104,6 +104,13 @@ public:
*/ */
int32_t extract(char *dest, int32_t capacity, UErrorCode &errorCode) const; int32_t extract(char *dest, int32_t capacity, UErrorCode &errorCode) const;
bool operator==(const CharString& other) const {
return len == other.length() && (len == 0 || uprv_memcmp(data(), other.data(), len) == 0);
}
bool operator!=(const CharString& other) const {
return !operator==(other);
}
bool operator==(StringPiece other) const { bool operator==(StringPiece other) const {
return len == other.length() && (len == 0 || uprv_memcmp(data(), other.data(), len) == 0); return len == other.length() && (len == 0 || uprv_memcmp(data(), other.data(), len) == 0);
} }

View File

@ -147,7 +147,7 @@ public:
if(umtx_atomic_dec(&refcount) <= 0) { if(umtx_atomic_dec(&refcount) <= 0) {
delete this; delete this;
} }
return 0; return nullptr;
} }
virtual ~SimpleFilteredSentenceBreakData(); virtual ~SimpleFilteredSentenceBreakData();

View File

@ -148,12 +148,12 @@ inline void Hashtable::initSize(UHashFunction *keyHash, UKeyComparator *keyComp,
} }
inline Hashtable::Hashtable(UKeyComparator *keyComp, UValueComparator *valueComp, inline Hashtable::Hashtable(UKeyComparator *keyComp, UValueComparator *valueComp,
UErrorCode& status) : hash(0) { UErrorCode& status) : hash(nullptr) {
init( uhash_hashUnicodeString, keyComp, valueComp, status); init( uhash_hashUnicodeString, keyComp, valueComp, status);
} }
inline Hashtable::Hashtable(UBool ignoreKeyCase, UErrorCode& status) inline Hashtable::Hashtable(UBool ignoreKeyCase, UErrorCode& status)
: hash(0) : hash(nullptr)
{ {
init(ignoreKeyCase ? uhash_hashCaselessUnicodeString init(ignoreKeyCase ? uhash_hashCaselessUnicodeString
: uhash_hashUnicodeString, : uhash_hashUnicodeString,
@ -164,7 +164,7 @@ inline Hashtable::Hashtable(UBool ignoreKeyCase, UErrorCode& status)
} }
inline Hashtable::Hashtable(UBool ignoreKeyCase, int32_t size, UErrorCode& status) inline Hashtable::Hashtable(UBool ignoreKeyCase, int32_t size, UErrorCode& status)
: hash(0) : hash(nullptr)
{ {
initSize(ignoreKeyCase ? uhash_hashCaselessUnicodeString initSize(ignoreKeyCase ? uhash_hashCaselessUnicodeString
: uhash_hashUnicodeString, : uhash_hashUnicodeString,
@ -175,13 +175,13 @@ inline Hashtable::Hashtable(UBool ignoreKeyCase, int32_t size, UErrorCode& statu
} }
inline Hashtable::Hashtable(UErrorCode& status) inline Hashtable::Hashtable(UErrorCode& status)
: hash(0) : hash(nullptr)
{ {
init(uhash_hashUnicodeString, uhash_compareUnicodeString, nullptr, status); init(uhash_hashUnicodeString, uhash_compareUnicodeString, nullptr, status);
} }
inline Hashtable::Hashtable() inline Hashtable::Hashtable()
: hash(0) : hash(nullptr)
{ {
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
init(uhash_hashUnicodeString, uhash_compareUnicodeString, nullptr, status); init(uhash_hashUnicodeString, uhash_compareUnicodeString, nullptr, status);

View File

@ -3,21 +3,21 @@
#include <utility> #include <utility>
#include "bytesinkutil.h" // CharStringByteSink #include "bytesinkutil.h" // StringByteSink<CharString>
#include "charstr.h" #include "charstr.h"
#include "cstring.h" #include "cstring.h"
#include "ulocimp.h" #include "ulocimp.h"
#include "unicode/localebuilder.h" #include "unicode/localebuilder.h"
#include "unicode/locid.h" #include "unicode/locid.h"
U_NAMESPACE_BEGIN namespace {
#define UPRV_ISDIGIT(c) (((c) >= '0') && ((c) <= '9')) inline bool UPRV_ISDIGIT(char c) { return c >= '0' && c <= '9'; }
#define UPRV_ISALPHANUM(c) (uprv_isASCIILetter(c) || UPRV_ISDIGIT(c) ) inline bool UPRV_ISALPHANUM(char c) { return uprv_isASCIILetter(c) || UPRV_ISDIGIT(c); }
constexpr const char* kAttributeKey = "attribute"; constexpr const char* kAttributeKey = "attribute";
static bool _isExtensionSubtags(char key, const char* s, int32_t len) { bool _isExtensionSubtags(char key, const char* s, int32_t len) {
switch (uprv_tolower(key)) { switch (uprv_tolower(key)) {
case 'u': case 'u':
return ultag_isUnicodeExtensionSubtags(s, len); return ultag_isUnicodeExtensionSubtags(s, len);
@ -30,6 +30,10 @@ static bool _isExtensionSubtags(char key, const char* s, int32_t len) {
} }
} }
} // namespace
U_NAMESPACE_BEGIN
LocaleBuilder::LocaleBuilder() : UObject(), status_(U_ZERO_ERROR), language_(), LocaleBuilder::LocaleBuilder() : UObject(), status_(U_ZERO_ERROR), language_(),
script_(), region_(), variant_(nullptr), extensions_(nullptr) script_(), region_(), variant_(nullptr), extensions_(nullptr)
{ {
@ -68,8 +72,10 @@ LocaleBuilder& LocaleBuilder::setLanguageTag(StringPiece tag)
return *this; return *this;
} }
static void setField(StringPiece input, char* dest, UErrorCode& errorCode, namespace {
UBool (*test)(const char*, int32_t)) {
void setField(StringPiece input, char* dest, UErrorCode& errorCode,
bool (*test)(const char*, int32_t)) {
if (U_FAILURE(errorCode)) { return; } if (U_FAILURE(errorCode)) { return; }
if (input.empty()) { if (input.empty()) {
dest[0] = '\0'; dest[0] = '\0';
@ -81,6 +87,8 @@ static void setField(StringPiece input, char* dest, UErrorCode& errorCode,
} }
} }
} // namespace
LocaleBuilder& LocaleBuilder::setLanguage(StringPiece language) LocaleBuilder& LocaleBuilder::setLanguage(StringPiece language)
{ {
setField(language, language_, status_, &ultag_isLanguageSubtag); setField(language, language_, status_, &ultag_isLanguageSubtag);
@ -99,7 +107,9 @@ LocaleBuilder& LocaleBuilder::setRegion(StringPiece region)
return *this; return *this;
} }
static void transform(char* data, int32_t len) { namespace {
void transform(char* data, int32_t len) {
for (int32_t i = 0; i < len; i++, data++) { for (int32_t i = 0; i < len; i++, data++) {
if (*data == '_') { if (*data == '_') {
*data = '-'; *data = '-';
@ -109,6 +119,8 @@ static void transform(char* data, int32_t len) {
} }
} }
} // namespace
LocaleBuilder& LocaleBuilder::setVariant(StringPiece variant) LocaleBuilder& LocaleBuilder::setVariant(StringPiece variant)
{ {
if (U_FAILURE(status_)) { return *this; } if (U_FAILURE(status_)) { return *this; }
@ -134,7 +146,9 @@ LocaleBuilder& LocaleBuilder::setVariant(StringPiece variant)
return *this; return *this;
} }
static bool namespace {
bool
_isKeywordValue(const char* key, const char* value, int32_t value_len) _isKeywordValue(const char* key, const char* value, int32_t value_len)
{ {
if (key[1] == '\0') { if (key[1] == '\0') {
@ -156,7 +170,7 @@ _isKeywordValue(const char* key, const char* value, int32_t value_len)
ultag_isUnicodeLocaleType(unicode_locale_type, -1); ultag_isUnicodeLocaleType(unicode_locale_type, -1);
} }
static void void
_copyExtensions(const Locale& from, icu::StringEnumeration *keywords, _copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
Locale& to, bool validate, UErrorCode& errorCode) Locale& to, bool validate, UErrorCode& errorCode)
{ {
@ -169,9 +183,7 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
} }
const char* key; const char* key;
while ((key = keywords->next(nullptr, errorCode)) != nullptr) { while ((key = keywords->next(nullptr, errorCode)) != nullptr) {
CharString value; auto value = from.getKeywordValue<CharString>(key, errorCode);
CharStringByteSink sink(&value);
from.getKeywordValue(key, sink, errorCode);
if (U_FAILURE(errorCode)) { return; } if (U_FAILURE(errorCode)) { return; }
if (uprv_strcmp(key, kAttributeKey) == 0) { if (uprv_strcmp(key, kAttributeKey) == 0) {
transform(value.data(), value.length()); transform(value.data(), value.length());
@ -186,9 +198,10 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
} }
} }
void static void
_clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode) _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
{ {
if (U_FAILURE(errorCode)) { return; }
// Clear Unicode attributes // Clear Unicode attributes
locale.setKeywordValue(kAttributeKey, "", errorCode); locale.setKeywordValue(kAttributeKey, "", errorCode);
@ -201,9 +214,10 @@ _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
} }
} }
static void void
_setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& errorCode) _setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& errorCode)
{ {
if (U_FAILURE(errorCode)) { return; }
// Add the unicode extensions to extensions_ // Add the unicode extensions to extensions_
CharString locale_str("und-u-", errorCode); CharString locale_str("und-u-", errorCode);
locale_str.append(value, errorCode); locale_str.append(value, errorCode);
@ -212,6 +226,8 @@ _setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& error
locale, false, errorCode); locale, false, errorCode);
} }
} // namespace
LocaleBuilder& LocaleBuilder::setExtension(char key, StringPiece value) LocaleBuilder& LocaleBuilder::setExtension(char key, StringPiece value)
{ {
if (U_FAILURE(status_)) { return *this; } if (U_FAILURE(status_)) { return *this; }
@ -289,10 +305,8 @@ LocaleBuilder& LocaleBuilder::addUnicodeLocaleAttribute(
return *this; return *this;
} }
CharString attributes;
CharStringByteSink sink(&attributes);
UErrorCode localErrorCode = U_ZERO_ERROR; UErrorCode localErrorCode = U_ZERO_ERROR;
extensions_->getKeywordValue(kAttributeKey, sink, localErrorCode); auto attributes = extensions_->getKeywordValue<CharString>(kAttributeKey, localErrorCode);
if (U_FAILURE(localErrorCode)) { if (U_FAILURE(localErrorCode)) {
CharString new_attributes(value_str.data(), status_); CharString new_attributes(value_str.data(), status_);
// No attributes, set the attribute. // No attributes, set the attribute.
@ -344,9 +358,7 @@ LocaleBuilder& LocaleBuilder::removeUnicodeLocaleAttribute(
} }
if (extensions_ == nullptr) { return *this; } if (extensions_ == nullptr) { return *this; }
UErrorCode localErrorCode = U_ZERO_ERROR; UErrorCode localErrorCode = U_ZERO_ERROR;
CharString attributes; auto attributes = extensions_->getKeywordValue<CharString>(kAttributeKey, localErrorCode);
CharStringByteSink sink(&attributes);
extensions_->getKeywordValue(kAttributeKey, sink, localErrorCode);
// get failure, just return // get failure, just return
if (U_FAILURE(localErrorCode)) { return *this; } if (U_FAILURE(localErrorCode)) { return *this; }
// Do not have any attributes, just return. // Do not have any attributes, just return.

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
// localematcher.cpp // localematcher.cpp
// created: 2019may08 Markus W. Scherer // created: 2019may08 Markus W. Scherer
#include <optional>
#include "unicode/utypes.h" #include "unicode/utypes.h"
#include "unicode/localebuilder.h" #include "unicode/localebuilder.h"
#include "unicode/localematcher.h" #include "unicode/localematcher.h"
@ -302,7 +304,7 @@ LocaleMatcher LocaleMatcher::Builder::build(UErrorCode &errorCode) const {
namespace { namespace {
LSR getMaximalLsrOrUnd(const XLikelySubtags &likelySubtags, const Locale &locale, LSR getMaximalLsrOrUnd(const LikelySubtags &likelySubtags, const Locale &locale,
UErrorCode &errorCode) { UErrorCode &errorCode) {
if (U_FAILURE(errorCode) || locale.isBogus() || *locale.getName() == 0 /* "und" */) { if (U_FAILURE(errorCode) || locale.isBogus() || *locale.getName() == 0 /* "und" */) {
return UND_LSR; return UND_LSR;
@ -338,7 +340,7 @@ int32_t LocaleMatcher::putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength
} }
LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) :
likelySubtags(*XLikelySubtags::getSingleton(errorCode)), likelySubtags(*LikelySubtags::getSingleton(errorCode)),
localeDistance(*LocaleDistance::getSingleton(errorCode)), localeDistance(*LocaleDistance::getSingleton(errorCode)),
thresholdDistance(builder.thresholdDistance_), thresholdDistance(builder.thresholdDistance_),
demotionPerDesiredLocale(0), demotionPerDesiredLocale(0),
@ -551,7 +553,7 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) noexcept {
class LocaleLsrIterator { class LocaleLsrIterator {
public: public:
LocaleLsrIterator(const XLikelySubtags &likelySubtags, Locale::Iterator &locales, LocaleLsrIterator(const LikelySubtags &likelySubtags, Locale::Iterator &locales,
ULocMatchLifetime lifetime) : ULocMatchLifetime lifetime) :
likelySubtags(likelySubtags), locales(locales), lifetime(lifetime) {} likelySubtags(likelySubtags), locales(locales), lifetime(lifetime) {}
@ -596,7 +598,7 @@ public:
} }
private: private:
const XLikelySubtags &likelySubtags; const LikelySubtags &likelySubtags;
Locale::Iterator &locales; Locale::Iterator &locales;
ULocMatchLifetime lifetime; ULocMatchLifetime lifetime;
const Locale *current = nullptr, *remembered = nullptr; const Locale *current = nullptr, *remembered = nullptr;
@ -605,10 +607,11 @@ private:
const Locale *LocaleMatcher::getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const { const Locale *LocaleMatcher::getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return nullptr; } if (U_FAILURE(errorCode)) { return nullptr; }
int32_t suppIndex = getBestSuppIndex( std::optional<int32_t> suppIndex = getBestSuppIndex(
getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode),
nullptr, errorCode); nullptr, errorCode);
return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; return U_SUCCESS(errorCode) && suppIndex.has_value() ? supportedLocales[*suppIndex]
: defaultLocale;
} }
const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales, const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales,
@ -618,12 +621,14 @@ const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales,
return defaultLocale; return defaultLocale;
} }
LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES);
int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); std::optional<int32_t> suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; return U_SUCCESS(errorCode) && suppIndex.has_value() ? supportedLocales[*suppIndex]
: defaultLocale;
} }
const Locale *LocaleMatcher::getBestMatchForListString( const Locale *LocaleMatcher::getBestMatchForListString(
StringPiece desiredLocaleList, UErrorCode &errorCode) const { StringPiece desiredLocaleList, UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return nullptr; }
LocalePriorityList list(desiredLocaleList, errorCode); LocalePriorityList list(desiredLocaleList, errorCode);
LocalePriorityList::Iterator iter = list.iterator(); LocalePriorityList::Iterator iter = list.iterator();
return getBestMatch(iter, errorCode); return getBestMatch(iter, errorCode);
@ -634,13 +639,13 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult(
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) {
return Result(nullptr, defaultLocale, -1, -1, false); return Result(nullptr, defaultLocale, -1, -1, false);
} }
int32_t suppIndex = getBestSuppIndex( std::optional<int32_t> suppIndex = getBestSuppIndex(
getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode),
nullptr, errorCode); nullptr, errorCode);
if (U_FAILURE(errorCode) || suppIndex < 0) { if (U_FAILURE(errorCode) || !suppIndex.has_value()) {
return Result(nullptr, defaultLocale, -1, -1, false); return Result(nullptr, defaultLocale, -1, -1, false);
} else { } else {
return Result(&desiredLocale, supportedLocales[suppIndex], 0, suppIndex, false); return Result(&desiredLocale, supportedLocales[*suppIndex], 0, *suppIndex, false);
} }
} }
@ -650,18 +655,19 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult(
return Result(nullptr, defaultLocale, -1, -1, false); return Result(nullptr, defaultLocale, -1, -1, false);
} }
LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES);
int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); std::optional<int32_t> suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
if (U_FAILURE(errorCode) || suppIndex < 0) { if (U_FAILURE(errorCode) || !suppIndex.has_value()) {
return Result(nullptr, defaultLocale, -1, -1, false); return Result(nullptr, defaultLocale, -1, -1, false);
} else { } else {
return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex], return Result(lsrIter.orphanRemembered(), supportedLocales[*suppIndex],
lsrIter.getBestDesiredIndex(), suppIndex, true); lsrIter.getBestDesiredIndex(), *suppIndex, true);
} }
} }
int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, std::optional<int32_t> LocaleMatcher::getBestSuppIndex(LSR desiredLSR,
LocaleLsrIterator *remainingIter,
UErrorCode &errorCode) const { UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return -1; } if (U_FAILURE(errorCode)) { return std::nullopt; }
int32_t desiredIndex = 0; int32_t desiredIndex = 0;
int32_t bestSupportedLsrIndex = -1; int32_t bestSupportedLsrIndex = -1;
for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(thresholdDistance);;) { for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(thresholdDistance);;) {
@ -684,7 +690,7 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai
bestShiftedDistance = LocaleDistance::getShiftedDistance(bestIndexAndDistance); bestShiftedDistance = LocaleDistance::getShiftedDistance(bestIndexAndDistance);
if (remainingIter != nullptr) { if (remainingIter != nullptr) {
remainingIter->rememberCurrent(desiredIndex, errorCode); remainingIter->rememberCurrent(desiredIndex, errorCode);
if (U_FAILURE(errorCode)) { return -1; } if (U_FAILURE(errorCode)) { return std::nullopt; }
} }
bestSupportedLsrIndex = LocaleDistance::getIndex(bestIndexAndDistance); bestSupportedLsrIndex = LocaleDistance::getIndex(bestIndexAndDistance);
} }
@ -695,20 +701,21 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai
break; break;
} }
desiredLSR = remainingIter->next(errorCode); desiredLSR = remainingIter->next(errorCode);
if (U_FAILURE(errorCode)) { return -1; } if (U_FAILURE(errorCode)) { return std::nullopt; }
++desiredIndex; ++desiredIndex;
} }
if (bestSupportedLsrIndex < 0) { if (bestSupportedLsrIndex < 0) {
// no good match // no good match
return -1; return std::nullopt;
} }
return supportedIndexes[bestSupportedLsrIndex]; return supportedIndexes[bestSupportedLsrIndex];
} }
UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported, UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported,
UErrorCode &errorCode) const { UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return false; }
LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode);
if (U_FAILURE(errorCode)) { return 0; } if (U_FAILURE(errorCode)) { return false; }
const LSR *pSuppLSR = &suppLSR; const LSR *pSuppLSR = &suppLSR;
int32_t indexAndDistance = localeDistance.getBestIndexAndDistance( int32_t indexAndDistance = localeDistance.getBestIndexAndDistance(
getMaximalLsrOrUnd(likelySubtags, desired, errorCode), getMaximalLsrOrUnd(likelySubtags, desired, errorCode),
@ -718,9 +725,10 @@ UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported,
} }
double LocaleMatcher::internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const { double LocaleMatcher::internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return 0.; }
// Returns the inverse of the distance: That is, 1-distance(desired, supported). // Returns the inverse of the distance: That is, 1-distance(desired, supported).
LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode);
if (U_FAILURE(errorCode)) { return 0; } if (U_FAILURE(errorCode)) { return 0.; }
const LSR *pSuppLSR = &suppLSR; const LSR *pSuppLSR = &suppLSR;
int32_t indexAndDistance = localeDistance.getBestIndexAndDistance( int32_t indexAndDistance = localeDistance.getBestIndexAndDistance(
getMaximalLsrOrUnd(likelySubtags, desired, errorCode), getMaximalLsrOrUnd(likelySubtags, desired, errorCode),

View File

@ -21,13 +21,13 @@ U_NAMESPACE_BEGIN
namespace { namespace {
int32_t hashLocale(const UHashTok token) { int32_t hashLocale(const UHashTok token) {
auto *locale = static_cast<const Locale *>(token.pointer); const auto* locale = static_cast<const Locale*>(token.pointer);
return locale->hashCode(); return locale->hashCode();
} }
UBool compareLocales(const UHashTok t1, const UHashTok t2) { UBool compareLocales(const UHashTok t1, const UHashTok t2) {
auto *l1 = static_cast<const Locale *>(t1.pointer); const auto* l1 = static_cast<const Locale*>(t1.pointer);
auto *l2 = static_cast<const Locale *>(t2.pointer); const auto* l2 = static_cast<const Locale*>(t2.pointer);
return *l1 == *l2; return *l1 == *l2;
} }

View File

@ -39,14 +39,10 @@ static icu::Locale* availableLocaleList = nullptr;
static int32_t availableLocaleListCount; static int32_t availableLocaleListCount;
static icu::UInitOnce gInitOnceLocale {}; static icu::UInitOnce gInitOnceLocale {};
U_NAMESPACE_END namespace {
U_CDECL_BEGIN UBool U_CALLCONV locale_available_cleanup()
static UBool U_CALLCONV locale_available_cleanup()
{ {
U_NAMESPACE_USE
if (availableLocaleList) { if (availableLocaleList) {
delete []availableLocaleList; delete []availableLocaleList;
availableLocaleList = nullptr; availableLocaleList = nullptr;
@ -57,9 +53,7 @@ static UBool U_CALLCONV locale_available_cleanup()
return true; return true;
} }
U_CDECL_END } // namespace
U_NAMESPACE_BEGIN
void U_CALLCONV locale_available_init() { void U_CALLCONV locale_available_init() {
// This function is a friend of class Locale. // This function is a friend of class Locale.
@ -107,10 +101,9 @@ icu::UInitOnce ginstalledLocalesInitOnce {};
class AvailableLocalesSink : public ResourceSink { class AvailableLocalesSink : public ResourceSink {
public: public:
void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) override { void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) override {
if (U_FAILURE(status)) { return; }
ResourceTable resIndexTable = value.getTable(status); ResourceTable resIndexTable = value.getTable(status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) { return; }
return;
}
for (int32_t i = 0; resIndexTable.getKeyAndValue(i, key, value); ++i) { for (int32_t i = 0; resIndexTable.getKeyAndValue(i, key, value); ++i) {
ULocAvailableType type; ULocAvailableType type;
if (uprv_strcmp(key, "InstalledLocales") == 0) { if (uprv_strcmp(key, "InstalledLocales") == 0) {
@ -144,7 +137,8 @@ class AvailableLocalesStringEnumeration : public StringEnumeration {
AvailableLocalesStringEnumeration(ULocAvailableType type) : fType(type) { AvailableLocalesStringEnumeration(ULocAvailableType type) : fType(type) {
} }
const char* next(int32_t *resultLength, UErrorCode&) override { const char* next(int32_t *resultLength, UErrorCode &status) override {
if (U_FAILURE(status)) { return nullptr; }
ULocAvailableType actualType = fType; ULocAvailableType actualType = fType;
int32_t actualIndex = fIndex++; int32_t actualIndex = fIndex++;
@ -176,11 +170,13 @@ class AvailableLocalesStringEnumeration : public StringEnumeration {
return result; return result;
} }
void reset(UErrorCode&) override { void reset(UErrorCode &status) override {
if (U_FAILURE(status)) { return; }
fIndex = 0; fIndex = 0;
} }
int32_t count(UErrorCode&) const override { int32_t count(UErrorCode &status) const override {
if (U_FAILURE(status)) { return 0; }
if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) { if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) {
return gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT] return gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT]
+ gAvailableLocaleCounts[ULOC_AVAILABLE_ONLY_LEGACY_ALIASES]; + gAvailableLocaleCounts[ULOC_AVAILABLE_ONLY_LEGACY_ALIASES];
@ -196,7 +192,7 @@ class AvailableLocalesStringEnumeration : public StringEnumeration {
/* ### Get available **************************************************/ /* ### Get available **************************************************/
static UBool U_CALLCONV uloc_cleanup() { UBool U_CALLCONV uloc_cleanup() {
for (int32_t i = 0; i < UPRV_LENGTHOF(gAvailableLocaleNames); i++) { for (int32_t i = 0; i < UPRV_LENGTHOF(gAvailableLocaleNames); i++) {
uprv_free(gAvailableLocaleNames[i]); uprv_free(gAvailableLocaleNames[i]);
gAvailableLocaleNames[i] = nullptr; gAvailableLocaleNames[i] = nullptr;
@ -209,7 +205,7 @@ static UBool U_CALLCONV uloc_cleanup() {
// Load Installed Locales. This function will be called exactly once // Load Installed Locales. This function will be called exactly once
// via the initOnce mechanism. // via the initOnce mechanism.
static void U_CALLCONV loadInstalledLocales(UErrorCode& status) { void U_CALLCONV loadInstalledLocales(UErrorCode& status) {
ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
icu::LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "res_index", &status)); icu::LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "res_index", &status));
@ -267,4 +263,3 @@ uloc_openAvailableByType(ULocAvailableType type, UErrorCode* status) {
} }
return uenum_openFromStringEnumeration(result.orphan(), status); return uenum_openFromStringEnumeration(result.orphan(), status);
} }

View File

@ -17,7 +17,7 @@ U_NAMESPACE_BEGIN
Locale LocaleBased::getLocale(ULocDataLocaleType type, UErrorCode& status) const { Locale LocaleBased::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
const char* id = getLocaleID(type, status); const char* id = getLocaleID(type, status);
return Locale((id != 0) ? id : ""); return Locale(id != nullptr ? id : "");
} }
const char* LocaleBased::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { const char* LocaleBased::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const {
@ -37,11 +37,11 @@ const char* LocaleBased::getLocaleID(ULocDataLocaleType type, UErrorCode& status
} }
void LocaleBased::setLocaleIDs(const char* validID, const char* actualID) { void LocaleBased::setLocaleIDs(const char* validID, const char* actualID) {
if (validID != 0) { if (validID != nullptr) {
uprv_strncpy(valid, validID, ULOC_FULLNAME_CAPACITY); uprv_strncpy(valid, validID, ULOC_FULLNAME_CAPACITY);
valid[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate valid[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate
} }
if (actualID != 0) { if (actualID != nullptr) {
uprv_strncpy(actual, actualID, ULOC_FULLNAME_CAPACITY); uprv_strncpy(actual, actualID, ULOC_FULLNAME_CAPACITY);
actual[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate actual[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate
} }

View File

@ -26,7 +26,6 @@
#include "unicode/uloc.h" #include "unicode/uloc.h"
#include "unicode/ures.h" #include "unicode/ures.h"
#include "unicode/ustring.h" #include "unicode/ustring.h"
#include "bytesinkutil.h"
#include "charstr.h" #include "charstr.h"
#include "cmemory.h" #include "cmemory.h"
#include "cstring.h" #include "cstring.h"
@ -60,7 +59,7 @@ Locale::getDisplayLanguage(const Locale &displayLocale,
int32_t length; int32_t length;
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -72,7 +71,7 @@ Locale::getDisplayLanguage(const Locale &displayLocale,
if(errorCode==U_BUFFER_OVERFLOW_ERROR) { if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
buffer=result.getBuffer(length); buffer=result.getBuffer(length);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -100,7 +99,7 @@ Locale::getDisplayScript(const Locale &displayLocale,
int32_t length; int32_t length;
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -112,7 +111,7 @@ Locale::getDisplayScript(const Locale &displayLocale,
if(errorCode==U_BUFFER_OVERFLOW_ERROR) { if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
buffer=result.getBuffer(length); buffer=result.getBuffer(length);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -140,7 +139,7 @@ Locale::getDisplayCountry(const Locale &displayLocale,
int32_t length; int32_t length;
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -152,7 +151,7 @@ Locale::getDisplayCountry(const Locale &displayLocale,
if(errorCode==U_BUFFER_OVERFLOW_ERROR) { if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
buffer=result.getBuffer(length); buffer=result.getBuffer(length);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -180,7 +179,7 @@ Locale::getDisplayVariant(const Locale &displayLocale,
int32_t length; int32_t length;
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -192,7 +191,7 @@ Locale::getDisplayVariant(const Locale &displayLocale,
if(errorCode==U_BUFFER_OVERFLOW_ERROR) { if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
buffer=result.getBuffer(length); buffer=result.getBuffer(length);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -220,7 +219,7 @@ Locale::getDisplayName(const Locale &displayLocale,
int32_t length; int32_t length;
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -232,7 +231,7 @@ Locale::getDisplayName(const Locale &displayLocale,
if(errorCode==U_BUFFER_OVERFLOW_ERROR) { if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
buffer=result.getBuffer(length); buffer=result.getBuffer(length);
if(buffer==0) { if (buffer == nullptr) {
result.truncate(0); result.truncate(0);
return result; return result;
} }
@ -276,50 +275,53 @@ U_NAMESPACE_END
U_NAMESPACE_USE U_NAMESPACE_USE
namespace {
/* ### Constants **************************************************/ /* ### Constants **************************************************/
/* These strings describe the resources we attempt to load from /* These strings describe the resources we attempt to load from
the locale ResourceBundle data file.*/ the locale ResourceBundle data file.*/
static const char _kLanguages[] = "Languages"; constexpr char _kLanguages[] = "Languages";
static const char _kScripts[] = "Scripts"; constexpr char _kScripts[] = "Scripts";
static const char _kScriptsStandAlone[] = "Scripts%stand-alone"; constexpr char _kScriptsStandAlone[] = "Scripts%stand-alone";
static const char _kCountries[] = "Countries"; constexpr char _kCountries[] = "Countries";
static const char _kVariants[] = "Variants"; constexpr char _kVariants[] = "Variants";
static const char _kKeys[] = "Keys"; constexpr char _kKeys[] = "Keys";
static const char _kTypes[] = "Types"; constexpr char _kTypes[] = "Types";
//static const char _kRootName[] = "root"; //constexpr char _kRootName[] = "root";
static const char _kCurrency[] = "currency"; constexpr char _kCurrency[] = "currency";
static const char _kCurrencies[] = "Currencies"; constexpr char _kCurrencies[] = "Currencies";
static const char _kLocaleDisplayPattern[] = "localeDisplayPattern"; constexpr char _kLocaleDisplayPattern[] = "localeDisplayPattern";
static const char _kPattern[] = "pattern"; constexpr char _kPattern[] = "pattern";
static const char _kSeparator[] = "separator"; constexpr char _kSeparator[] = "separator";
/* ### Display name **************************************************/ /* ### Display name **************************************************/
static int32_t int32_t
_getStringOrCopyKey(const char *path, const char *locale, _getStringOrCopyKey(const char *path, const char *locale,
const char *tableKey, const char *tableKey,
const char* subTableKey, const char* subTableKey,
const char *itemKey, const char *itemKey,
const char *substitute, const char *substitute,
char16_t *dest, int32_t destCapacity, char16_t *dest, int32_t destCapacity,
UErrorCode *pErrorCode) { UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return 0; }
const char16_t *s = nullptr; const char16_t *s = nullptr;
int32_t length = 0; int32_t length = 0;
if(itemKey==nullptr) { if(itemKey==nullptr) {
/* top-level item: normal resource bundle access */ /* top-level item: normal resource bundle access */
icu::LocalUResourceBundlePointer rb(ures_open(path, locale, pErrorCode)); icu::LocalUResourceBundlePointer rb(ures_open(path, locale, &errorCode));
if(U_SUCCESS(*pErrorCode)) { if(U_SUCCESS(errorCode)) {
s=ures_getStringByKey(rb.getAlias(), tableKey, &length, pErrorCode); s=ures_getStringByKey(rb.getAlias(), tableKey, &length, &errorCode);
/* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */ /* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */
} }
} else { } else {
bool isLanguageCode = (uprv_strncmp(tableKey, _kLanguages, 9) == 0); bool isLanguageCode = (uprv_strncmp(tableKey, _kLanguages, 9) == 0);
/* Language code should not be a number. If it is, set the error code. */ /* Language code should not be a number. If it is, set the error code. */
if (isLanguageCode && uprv_strtol(itemKey, nullptr, 10)) { if (isLanguageCode && uprv_strtol(itemKey, nullptr, 10)) {
*pErrorCode = U_MISSING_RESOURCE_ERROR; errorCode = U_MISSING_RESOURCE_ERROR;
} else { } else {
/* second-level item, use special fallback */ /* second-level item, use special fallback */
s=uloc_getTableStringWithFallback(path, locale, s=uloc_getTableStringWithFallback(path, locale,
@ -327,22 +329,22 @@ _getStringOrCopyKey(const char *path, const char *locale,
subTableKey, subTableKey,
itemKey, itemKey,
&length, &length,
pErrorCode); &errorCode);
if (U_FAILURE(*pErrorCode) && isLanguageCode && itemKey != nullptr) { if (U_FAILURE(errorCode) && isLanguageCode && itemKey != nullptr) {
// convert itemKey locale code to canonical form and try again, ICU-20870 // convert itemKey locale code to canonical form and try again, ICU-20870
*pErrorCode = U_ZERO_ERROR; errorCode = U_ZERO_ERROR;
Locale canonKey = Locale::createCanonical(itemKey); Locale canonKey = Locale::createCanonical(itemKey);
s=uloc_getTableStringWithFallback(path, locale, s=uloc_getTableStringWithFallback(path, locale,
tableKey, tableKey,
subTableKey, subTableKey,
canonKey.getName(), canonKey.getName(),
&length, &length,
pErrorCode); &errorCode);
} }
} }
} }
if(U_SUCCESS(*pErrorCode)) { if(U_SUCCESS(errorCode)) {
int32_t copyLength=uprv_min(length, destCapacity); int32_t copyLength=uprv_min(length, destCapacity);
if(copyLength>0 && s != nullptr) { if(copyLength>0 && s != nullptr) {
u_memcpy(dest, s, copyLength); u_memcpy(dest, s, copyLength);
@ -351,67 +353,63 @@ _getStringOrCopyKey(const char *path, const char *locale,
/* no string from a resource bundle: convert the substitute */ /* no string from a resource bundle: convert the substitute */
length=(int32_t)uprv_strlen(substitute); length=(int32_t)uprv_strlen(substitute);
u_charsToUChars(substitute, dest, uprv_min(length, destCapacity)); u_charsToUChars(substitute, dest, uprv_min(length, destCapacity));
*pErrorCode=U_USING_DEFAULT_WARNING; errorCode = U_USING_DEFAULT_WARNING;
} }
return u_terminateUChars(dest, destCapacity, length, pErrorCode); return u_terminateUChars(dest, destCapacity, length, &errorCode);
} }
typedef int32_t U_CALLCONV UDisplayNameGetter(const char *, char *, int32_t, UErrorCode *); using UDisplayNameGetter = icu::CharString(const char*, UErrorCode&);
static int32_t int32_t
_getDisplayNameForComponent(const char *locale, _getDisplayNameForComponent(const char *locale,
const char *displayLocale, const char *displayLocale,
char16_t *dest, int32_t destCapacity, char16_t *dest, int32_t destCapacity,
UDisplayNameGetter *getter, UDisplayNameGetter *getter,
const char *tag, const char *tag,
UErrorCode *pErrorCode) { UErrorCode &errorCode) {
char localeBuffer[ULOC_FULLNAME_CAPACITY*4]; if (U_FAILURE(errorCode)) { return 0; }
int32_t length;
UErrorCode localStatus; UErrorCode localStatus;
const char* root = nullptr; const char* root = nullptr;
/* argument checking */
if(pErrorCode==nullptr || U_FAILURE(*pErrorCode)) {
return 0;
}
if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) { if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) {
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; errorCode = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return 0;
} }
localStatus = U_ZERO_ERROR; localStatus = U_ZERO_ERROR;
length=(*getter)(locale, localeBuffer, sizeof(localeBuffer), &localStatus); icu::CharString localeBuffer = (*getter)(locale, localStatus);
if(U_FAILURE(localStatus) || localStatus==U_STRING_NOT_TERMINATED_WARNING) { if (U_FAILURE(localStatus)) {
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; errorCode = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return 0;
} }
if(length==0) { if (localeBuffer.isEmpty()) {
// For the display name, we treat this as unknown language (ICU-20273). // For the display name, we treat this as unknown language (ICU-20273).
if (getter == uloc_getLanguage) { if (getter == ulocimp_getLanguage) {
uprv_strcpy(localeBuffer, "und"); localeBuffer.append("und", errorCode);
} else { } else {
return u_terminateUChars(dest, destCapacity, 0, pErrorCode); return u_terminateUChars(dest, destCapacity, 0, &errorCode);
} }
} }
root = tag == _kCountries ? U_ICUDATA_REGION : U_ICUDATA_LANG; root = tag == _kCountries ? U_ICUDATA_REGION : U_ICUDATA_LANG;
return _getStringOrCopyKey(root, displayLocale, return _getStringOrCopyKey(root, displayLocale,
tag, nullptr, localeBuffer, tag, nullptr, localeBuffer.data(),
localeBuffer, localeBuffer.data(),
dest, destCapacity, dest, destCapacity,
pErrorCode); errorCode);
} }
} // namespace
U_CAPI int32_t U_EXPORT2 U_CAPI int32_t U_EXPORT2
uloc_getDisplayLanguage(const char *locale, uloc_getDisplayLanguage(const char *locale,
const char *displayLocale, const char *displayLocale,
char16_t *dest, int32_t destCapacity, char16_t *dest, int32_t destCapacity,
UErrorCode *pErrorCode) { UErrorCode *pErrorCode) {
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
uloc_getLanguage, _kLanguages, pErrorCode); ulocimp_getLanguage, _kLanguages, *pErrorCode);
} }
U_CAPI int32_t U_EXPORT2 U_CAPI int32_t U_EXPORT2
@ -420,19 +418,20 @@ uloc_getDisplayScript(const char* locale,
char16_t *dest, int32_t destCapacity, char16_t *dest, int32_t destCapacity,
UErrorCode *pErrorCode) UErrorCode *pErrorCode)
{ {
if (U_FAILURE(*pErrorCode)) { return 0; }
UErrorCode err = U_ZERO_ERROR; UErrorCode err = U_ZERO_ERROR;
int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
uloc_getScript, _kScriptsStandAlone, &err); ulocimp_getScript, _kScriptsStandAlone, err);
if (destCapacity == 0 && err == U_BUFFER_OVERFLOW_ERROR) { if (destCapacity == 0 && err == U_BUFFER_OVERFLOW_ERROR) {
// For preflight, return the max of the value and the fallback. // For preflight, return the max of the value and the fallback.
int32_t fallback_res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, int32_t fallback_res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
uloc_getScript, _kScripts, pErrorCode); ulocimp_getScript, _kScripts, *pErrorCode);
return (fallback_res > res) ? fallback_res : res; return (fallback_res > res) ? fallback_res : res;
} }
if ( err == U_USING_DEFAULT_WARNING ) { if ( err == U_USING_DEFAULT_WARNING ) {
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
uloc_getScript, _kScripts, pErrorCode); ulocimp_getScript, _kScripts, *pErrorCode);
} else { } else {
*pErrorCode = err; *pErrorCode = err;
return res; return res;
@ -446,7 +445,7 @@ uloc_getDisplayScriptInContext(const char* locale,
UErrorCode *pErrorCode) UErrorCode *pErrorCode)
{ {
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
uloc_getScript, _kScripts, pErrorCode); ulocimp_getScript, _kScripts, *pErrorCode);
} }
U_CAPI int32_t U_EXPORT2 U_CAPI int32_t U_EXPORT2
@ -455,7 +454,7 @@ uloc_getDisplayCountry(const char *locale,
char16_t *dest, int32_t destCapacity, char16_t *dest, int32_t destCapacity,
UErrorCode *pErrorCode) { UErrorCode *pErrorCode) {
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
uloc_getCountry, _kCountries, pErrorCode); ulocimp_getRegion, _kCountries, *pErrorCode);
} }
/* /*
@ -469,7 +468,7 @@ uloc_getDisplayVariant(const char *locale,
char16_t *dest, int32_t destCapacity, char16_t *dest, int32_t destCapacity,
UErrorCode *pErrorCode) { UErrorCode *pErrorCode) {
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
uloc_getVariant, _kVariants, pErrorCode); ulocimp_getVariant, _kVariants, *pErrorCode);
} }
/* Instead of having a separate pass for 'special' patterns, reintegrate the two /* Instead of having a separate pass for 'special' patterns, reintegrate the two
@ -809,7 +808,7 @@ uloc_getDisplayKeyword(const char* keyword,
keyword, keyword,
keyword, keyword,
dest, destCapacity, dest, destCapacity,
status); *status);
} }
@ -836,11 +835,7 @@ uloc_getDisplayKeywordValue( const char* locale,
} }
/* get the keyword value */ /* get the keyword value */
CharString keywordValue; CharString keywordValue = ulocimp_getKeywordValue(locale, keyword, *status);
{
CharStringByteSink sink(&keywordValue);
ulocimp_getKeywordValue(locale, keyword, sink, status);
}
/* /*
* if the keyword is equal to currency .. then to get the display name * if the keyword is equal to currency .. then to get the display name
@ -897,6 +892,6 @@ uloc_getDisplayKeywordValue( const char* locale,
keywordValue.data(), keywordValue.data(),
keywordValue.data(), keywordValue.data(),
dest, destCapacity, dest, destCapacity,
status); *status);
} }
} }

View File

@ -59,7 +59,7 @@ UBool U_CALLCONV cleanup() {
void U_CALLCONV LocaleDistance::initLocaleDistance(UErrorCode &errorCode) { void U_CALLCONV LocaleDistance::initLocaleDistance(UErrorCode &errorCode) {
// This function is invoked only via umtx_initOnce(). // This function is invoked only via umtx_initOnce().
U_ASSERT(gLocaleDistance == nullptr); U_ASSERT(gLocaleDistance == nullptr);
const XLikelySubtags &likely = *XLikelySubtags::getSingleton(errorCode); const LikelySubtags &likely = *LikelySubtags::getSingleton(errorCode);
if (U_FAILURE(errorCode)) { return; } if (U_FAILURE(errorCode)) { return; }
const LocaleDistanceData &data = likely.getDistanceData(); const LocaleDistanceData &data = likely.getDistanceData();
if (data.distanceTrieBytes == nullptr || if (data.distanceTrieBytes == nullptr ||
@ -83,7 +83,7 @@ const LocaleDistance *LocaleDistance::getSingleton(UErrorCode &errorCode) {
return gLocaleDistance; return gLocaleDistance;
} }
LocaleDistance::LocaleDistance(const LocaleDistanceData &data, const XLikelySubtags &likely) : LocaleDistance::LocaleDistance(const LocaleDistanceData &data, const LikelySubtags &likely) :
likelySubtags(likely), likelySubtags(likely),
trie(data.distanceTrieBytes), trie(data.distanceTrieBytes),
regionToPartitionsIndex(data.regionToPartitions), partitionArrays(data.partitions), regionToPartitionsIndex(data.regionToPartitions), partitionArrays(data.partitions),
@ -119,7 +119,7 @@ int32_t LocaleDistance::getBestIndexAndDistance(
uint64_t desLangState = desLangDistance >= 0 && supportedLSRsLength > 1 ? iter.getState64() : 0; uint64_t desLangState = desLangDistance >= 0 && supportedLSRsLength > 1 ? iter.getState64() : 0;
// Index of the supported LSR with the lowest distance. // Index of the supported LSR with the lowest distance.
int32_t bestIndex = -1; int32_t bestIndex = -1;
// Cached lookup info from XLikelySubtags.compareLikely(). // Cached lookup info from LikelySubtags.compareLikely().
int32_t bestLikelyInfo = -1; int32_t bestLikelyInfo = -1;
for (int32_t slIndex = 0; slIndex < supportedLSRsLength; ++slIndex) { for (int32_t slIndex = 0; slIndex < supportedLSRsLength; ++slIndex) {
const LSR &supported = *supportedLSRs[slIndex]; const LSR &supported = *supportedLSRs[slIndex];
@ -399,7 +399,7 @@ int32_t LocaleDistance::trieNext(BytesTrie &iter, const char *s, bool wantValue)
} }
} }
UBool LocaleDistance::isParadigmLSR(const LSR &lsr) const { bool LocaleDistance::isParadigmLSR(const LSR &lsr) const {
// Linear search for a very short list (length 6 as of 2019), // Linear search for a very short list (length 6 as of 2019),
// because we look for equivalence not equality, and // because we look for equivalence not equality, and
// because it's easy. // because it's easy.

View File

@ -62,7 +62,7 @@ public:
ULocMatchFavorSubtag favorSubtag, ULocMatchFavorSubtag favorSubtag,
ULocMatchDirection direction) const; ULocMatchDirection direction) const;
UBool isParadigmLSR(const LSR &lsr) const; bool isParadigmLSR(const LSR &lsr) const;
int32_t getDefaultScriptDistance() const { int32_t getDefaultScriptDistance() const {
return defaultScriptDistance; return defaultScriptDistance;
@ -83,13 +83,13 @@ private:
// tic constexpr int32_t MAX_INDEX = 0x1fffff; // avoids sign bit // tic constexpr int32_t MAX_INDEX = 0x1fffff; // avoids sign bit
static constexpr int32_t INDEX_NEG_1 = 0xfffffc00; static constexpr int32_t INDEX_NEG_1 = 0xfffffc00;
LocaleDistance(const LocaleDistanceData &data, const XLikelySubtags &likely); LocaleDistance(const LocaleDistanceData &data, const LikelySubtags &likely);
LocaleDistance(const LocaleDistance &other) = delete; LocaleDistance(const LocaleDistance &other) = delete;
LocaleDistance &operator=(const LocaleDistance &other) = delete; LocaleDistance &operator=(const LocaleDistance &other) = delete;
static void initLocaleDistance(UErrorCode &errorCode); static void initLocaleDistance(UErrorCode &errorCode);
UBool isMatch(const LSR &desired, const LSR &supported, bool isMatch(const LSR &desired, const LSR &supported,
int32_t shiftedThreshold, ULocMatchFavorSubtag favorSubtag) const { int32_t shiftedThreshold, ULocMatchFavorSubtag favorSubtag) const {
const LSR *pSupp = &supported; const LSR *pSupp = &supported;
return getBestIndexAndDistance( return getBestIndexAndDistance(
@ -119,7 +119,7 @@ private:
return defaultRegionDistance; return defaultRegionDistance;
} }
const XLikelySubtags &likelySubtags; const LikelySubtags &likelySubtags;
// The trie maps each dlang+slang+dscript+sscript+dregion+sregion // The trie maps each dlang+slang+dscript+sscript+dregion+sregion
// (encoded in ASCII with bit 7 set on the last character of each subtag) to a distance. // (encoded in ASCII with bit 7 set on the last character of each subtag) to a distance.

View File

@ -18,45 +18,17 @@
#include "unicode/udisplaycontext.h" #include "unicode/udisplaycontext.h"
#include "unicode/brkiter.h" #include "unicode/brkiter.h"
#include "unicode/ucurr.h" #include "unicode/ucurr.h"
#include "bytesinkutil.h"
#include "charstr.h"
#include "cmemory.h" #include "cmemory.h"
#include "cstring.h" #include "cstring.h"
#include "mutex.h" #include "mutex.h"
#include "uassert.h"
#include "ulocimp.h" #include "ulocimp.h"
#include "umutex.h" #include "umutex.h"
#include "ureslocs.h" #include "ureslocs.h"
#include "uresimp.h" #include "uresimp.h"
#include <stdarg.h>
/**
* Concatenate a number of null-terminated strings to buffer, leaving a
* null-terminated string. The last argument should be the null pointer.
* Return the length of the string in the buffer, not counting the trailing
* null. Return -1 if there is an error (buffer is null, or buflen < 1).
*/
static int32_t ncat(char *buffer, uint32_t buflen, ...) {
va_list args;
char *str;
char *p = buffer;
const char* e = buffer + buflen - 1;
if (buffer == nullptr || buflen < 1) {
return -1;
}
va_start(args, buflen);
while ((str = va_arg(args, char *)) != 0) {
char c;
while (p != e && (c = *str++) != 0) {
*p++ = c;
}
}
*p = 0;
va_end(args);
return static_cast<int32_t>(p - buffer);
}
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -64,12 +36,13 @@ U_NAMESPACE_BEGIN
// Access resource data for locale components. // Access resource data for locale components.
// Wrap code in uloc.c for now. // Wrap code in uloc.c for now.
class ICUDataTable { class ICUDataTable {
const char* path; const char* const path;
Locale locale; Locale locale;
public: public:
// Note: path should be a pointer to a statically allocated string.
ICUDataTable(const char* path, const Locale& locale); ICUDataTable(const char* path, const Locale& locale);
~ICUDataTable(); ~ICUDataTable() = default;
const Locale& getLocale(); const Locale& getLocale();
@ -95,23 +68,9 @@ ICUDataTable::getNoFallback(const char* tableKey, const char* itemKey, UnicodeSt
} }
ICUDataTable::ICUDataTable(const char* path, const Locale& locale) ICUDataTable::ICUDataTable(const char* path, const Locale& locale)
: path(nullptr), locale(Locale::getRoot()) : path(path), locale(locale)
{ {
if (path) { U_ASSERT(path != nullptr);
int32_t len = static_cast<int32_t>(uprv_strlen(path));
this->path = (const char*) uprv_malloc(len + 1);
if (this->path) {
uprv_strcpy((char *)this->path, path);
this->locale = locale;
}
}
}
ICUDataTable::~ICUDataTable() {
if (path) {
uprv_free((void*) path);
path = nullptr;
}
} }
const Locale& const Locale&
@ -305,7 +264,7 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames {
}; };
// Capitalization transforms. For each usage type, indicates whether to titlecase for // Capitalization transforms. For each usage type, indicates whether to titlecase for
// the context specified in capitalizationContext (which we know at construction time) // the context specified in capitalizationContext (which we know at construction time)
UBool fCapitalization[kCapContextUsageCount]; bool fCapitalization[kCapContextUsageCount];
public: public:
// constructor // constructor
@ -341,12 +300,12 @@ private:
UnicodeString& result, bool substitute) const; UnicodeString& result, bool substitute) const;
UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const; UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const;
UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const; UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const;
UnicodeString& scriptDisplayName(const char* script, UnicodeString& result, UBool skipAdjust) const; UnicodeString& scriptDisplayName(const char* script, UnicodeString& result, bool skipAdjust) const;
UnicodeString& regionDisplayName(const char* region, UnicodeString& result, UBool skipAdjust) const; UnicodeString& regionDisplayName(const char* region, UnicodeString& result, bool skipAdjust) const;
UnicodeString& variantDisplayName(const char* variant, UnicodeString& result, UBool skipAdjust) const; UnicodeString& variantDisplayName(const char* variant, UnicodeString& result, bool skipAdjust) const;
UnicodeString& keyDisplayName(const char* key, UnicodeString& result, UBool skipAdjust) const; UnicodeString& keyDisplayName(const char* key, UnicodeString& result, bool skipAdjust) const;
UnicodeString& keyValueDisplayName(const char* key, const char* value, UnicodeString& keyValueDisplayName(const char* key, const char* value,
UnicodeString& result, UBool skipAdjust) const; UnicodeString& result, bool skipAdjust) const;
void initialize(); void initialize();
struct CapitalizationContextSink; struct CapitalizationContextSink;
@ -399,7 +358,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
} }
struct LocaleDisplayNamesImpl::CapitalizationContextSink : public ResourceSink { struct LocaleDisplayNamesImpl::CapitalizationContextSink : public ResourceSink {
UBool hasCapitalizationUsage; bool hasCapitalizationUsage;
LocaleDisplayNamesImpl& parent; LocaleDisplayNamesImpl& parent;
CapitalizationContextSink(LocaleDisplayNamesImpl& _parent) CapitalizationContextSink(LocaleDisplayNamesImpl& _parent)
@ -490,7 +449,7 @@ LocaleDisplayNamesImpl::initialize() {
#if !UCONFIG_NO_BREAK_ITERATION #if !UCONFIG_NO_BREAK_ITERATION
// Only get the context data if we need it! This is a const object so we know now... // Only get the context data if we need it! This is a const object so we know now...
// Also check whether we will need a break iterator (depends on the data) // Also check whether we will need a break iterator (depends on the data)
UBool needBrkIter = false; bool needBrkIter = false;
if (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_STANDALONE) { if (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_STANDALONE) {
LocalUResourceBundlePointer resource(ures_open(nullptr, locale.getName(), &status)); LocalUResourceBundlePointer resource(ures_open(nullptr, locale.getName(), &status));
if (U_FAILURE(status)) { return; } if (U_FAILURE(status)) { return; }
@ -582,38 +541,53 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
const char* country = loc.getCountry(); const char* country = loc.getCountry();
const char* variant = loc.getVariant(); const char* variant = loc.getVariant();
UBool hasScript = uprv_strlen(script) > 0; bool hasScript = uprv_strlen(script) > 0;
UBool hasCountry = uprv_strlen(country) > 0; bool hasCountry = uprv_strlen(country) > 0;
UBool hasVariant = uprv_strlen(variant) > 0; bool hasVariant = uprv_strlen(variant) > 0;
if (dialectHandling == ULDN_DIALECT_NAMES) { if (dialectHandling == ULDN_DIALECT_NAMES) {
char buffer[ULOC_FULLNAME_CAPACITY]; UErrorCode status = U_ZERO_ERROR;
CharString buffer;
do { // loop construct is so we can break early out of search do { // loop construct is so we can break early out of search
if (hasScript && hasCountry) { if (hasScript && hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0); buffer.append(lang, status)
localeIdName(buffer, resultName, false); .append('_', status)
.append(script, status)
.append('_', status)
.append(country, status);
if (U_SUCCESS(status)) {
localeIdName(buffer.data(), resultName, false);
if (!resultName.isBogus()) { if (!resultName.isBogus()) {
hasScript = false; hasScript = false;
hasCountry = false; hasCountry = false;
break; break;
} }
} }
}
if (hasScript) { if (hasScript) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0); buffer.append(lang, status)
localeIdName(buffer, resultName, false); .append('_', status)
.append(script, status);
if (U_SUCCESS(status)) {
localeIdName(buffer.data(), resultName, false);
if (!resultName.isBogus()) { if (!resultName.isBogus()) {
hasScript = false; hasScript = false;
break; break;
} }
} }
}
if (hasCountry) { if (hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0); buffer.append(lang, status)
localeIdName(buffer, resultName, false); .append('_', status)
.append(country, status);
if (U_SUCCESS(status)) {
localeIdName(buffer.data(), resultName, false);
if (!resultName.isBogus()) { if (!resultName.isBogus()) {
hasCountry = false; hasCountry = false;
break; break;
} }
} }
}
} while (false); } while (false);
} }
if (resultName.isBogus() || resultName.isEmpty()) { if (resultName.isBogus() || resultName.isEmpty()) {
@ -658,21 +632,19 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
LocalPointer<StringEnumeration> e(loc.createKeywords(status)); LocalPointer<StringEnumeration> e(loc.createKeywords(status));
if (e.isValid() && U_SUCCESS(status)) { if (e.isValid() && U_SUCCESS(status)) {
UnicodeString temp2; UnicodeString temp2;
char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY
const char* key; const char* key;
while ((key = e->next((int32_t *)0, status)) != nullptr) { while ((key = e->next((int32_t*)nullptr, status)) != nullptr) {
value[0] = 0; auto value = loc.getKeywordValue<CharString>(key, status);
loc.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status); if (U_FAILURE(status)) {
if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
return result; return result;
} }
keyDisplayName(key, temp, true); keyDisplayName(key, temp, true);
temp.findAndReplace(formatOpenParen, formatReplaceOpenParen); temp.findAndReplace(formatOpenParen, formatReplaceOpenParen);
temp.findAndReplace(formatCloseParen, formatReplaceCloseParen); temp.findAndReplace(formatCloseParen, formatReplaceCloseParen);
keyValueDisplayName(key, value, temp2, true); keyValueDisplayName(key, value.data(), temp2, true);
temp2.findAndReplace(formatOpenParen, formatReplaceOpenParen); temp2.findAndReplace(formatOpenParen, formatReplaceOpenParen);
temp2.findAndReplace(formatCloseParen, formatReplaceCloseParen); temp2.findAndReplace(formatCloseParen, formatReplaceCloseParen);
if (temp2 != UnicodeString(value, -1, US_INV)) { if (temp2 != UnicodeString(value.data(), -1, US_INV)) {
appendWithSep(resultRemainder, temp2); appendWithSep(resultRemainder, temp2);
} else if (temp != UnicodeString(key, -1, US_INV)) { } else if (temp != UnicodeString(key, -1, US_INV)) {
UnicodeString temp3; UnicodeString temp3;
@ -779,7 +751,7 @@ LocaleDisplayNamesImpl::languageDisplayName(const char* lang,
UnicodeString& UnicodeString&
LocaleDisplayNamesImpl::scriptDisplayName(const char* script, LocaleDisplayNamesImpl::scriptDisplayName(const char* script,
UnicodeString& result, UnicodeString& result,
UBool skipAdjust) const { bool skipAdjust) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) { if (nameLength == UDISPCTX_LENGTH_SHORT) {
langData.getNoFallback("Scripts%short", script, result); langData.getNoFallback("Scripts%short", script, result);
if (!result.isBogus()) { if (!result.isBogus()) {
@ -809,7 +781,7 @@ LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode,
UnicodeString& UnicodeString&
LocaleDisplayNamesImpl::regionDisplayName(const char* region, LocaleDisplayNamesImpl::regionDisplayName(const char* region,
UnicodeString& result, UnicodeString& result,
UBool skipAdjust) const { bool skipAdjust) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) { if (nameLength == UDISPCTX_LENGTH_SHORT) {
regionData.getNoFallback("Countries%short", region, result); regionData.getNoFallback("Countries%short", region, result);
if (!result.isBogus()) { if (!result.isBogus()) {
@ -834,7 +806,7 @@ LocaleDisplayNamesImpl::regionDisplayName(const char* region,
UnicodeString& UnicodeString&
LocaleDisplayNamesImpl::variantDisplayName(const char* variant, LocaleDisplayNamesImpl::variantDisplayName(const char* variant,
UnicodeString& result, UnicodeString& result,
UBool skipAdjust) const { bool skipAdjust) const {
// don't have a resource for short variant names // don't have a resource for short variant names
if (substitute == UDISPCTX_SUBSTITUTE) { if (substitute == UDISPCTX_SUBSTITUTE) {
langData.get("Variants", variant, result); langData.get("Variants", variant, result);
@ -853,7 +825,7 @@ LocaleDisplayNamesImpl::variantDisplayName(const char* variant,
UnicodeString& UnicodeString&
LocaleDisplayNamesImpl::keyDisplayName(const char* key, LocaleDisplayNamesImpl::keyDisplayName(const char* key,
UnicodeString& result, UnicodeString& result,
UBool skipAdjust) const { bool skipAdjust) const {
// don't have a resource for short key names // don't have a resource for short key names
if (substitute == UDISPCTX_SUBSTITUTE) { if (substitute == UDISPCTX_SUBSTITUTE) {
langData.get("Keys", key, result); langData.get("Keys", key, result);
@ -873,7 +845,7 @@ UnicodeString&
LocaleDisplayNamesImpl::keyValueDisplayName(const char* key, LocaleDisplayNamesImpl::keyValueDisplayName(const char* key,
const char* value, const char* value,
UnicodeString& result, UnicodeString& result,
UBool skipAdjust) const { bool skipAdjust) const {
if (uprv_strcmp(key, "currency") == 0) { if (uprv_strcmp(key, "currency") == 0) {
// ICU4C does not have ICU4J CurrencyDisplayInfo equivalent for now. // ICU4C does not have ICU4J CurrencyDisplayInfo equivalent for now.
UErrorCode sts = U_ZERO_ERROR; UErrorCode sts = U_ZERO_ERROR;
@ -939,7 +911,7 @@ uldn_open(const char * locale,
UDialectHandling dialectHandling, UDialectHandling dialectHandling,
UErrorCode *pErrorCode) { UErrorCode *pErrorCode) {
if (U_FAILURE(*pErrorCode)) { if (U_FAILURE(*pErrorCode)) {
return 0; return nullptr;
} }
if (locale == nullptr) { if (locale == nullptr) {
locale = uloc_getDefault(); locale = uloc_getDefault();
@ -952,7 +924,7 @@ uldn_openForContext(const char * locale,
UDisplayContext *contexts, int32_t length, UDisplayContext *contexts, int32_t length,
UErrorCode *pErrorCode) { UErrorCode *pErrorCode) {
if (U_FAILURE(*pErrorCode)) { if (U_FAILURE(*pErrorCode)) {
return 0; return nullptr;
} }
if (locale == nullptr) { if (locale == nullptr) {
locale = uloc_getDefault(); locale = uloc_getDefault();

View File

@ -57,10 +57,6 @@
#include "ustr_imp.h" #include "ustr_imp.h"
#include "uvector.h" #include "uvector.h"
U_CDECL_BEGIN
static UBool U_CALLCONV locale_cleanup();
U_CDECL_END
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
static Locale *gLocaleCache = nullptr; static Locale *gLocaleCache = nullptr;
@ -106,16 +102,17 @@ typedef enum ELocalePos {
eMAX_LOCALES eMAX_LOCALES
} ELocalePos; } ELocalePos;
U_CDECL_BEGIN namespace {
// //
// Deleter function for Locales owned by the default Locale hash table/ // Deleter function for Locales owned by the default Locale hash table/
// //
static void U_CALLCONV void U_CALLCONV
deleteLocale(void *obj) { deleteLocale(void *obj) {
delete (icu::Locale *) obj; delete (icu::Locale *) obj;
} }
static UBool U_CALLCONV locale_cleanup() UBool U_CALLCONV locale_cleanup()
{ {
U_NAMESPACE_USE U_NAMESPACE_USE
@ -131,8 +128,7 @@ static UBool U_CALLCONV locale_cleanup()
return true; return true;
} }
void U_CALLCONV locale_init(UErrorCode &status) {
static void U_CALLCONV locale_init(UErrorCode &status) {
U_NAMESPACE_USE U_NAMESPACE_USE
U_ASSERT(gLocaleCache == nullptr); U_ASSERT(gLocaleCache == nullptr);
@ -163,7 +159,7 @@ static void U_CALLCONV locale_init(UErrorCode &status) {
gLocaleCache[eCANADA_FRENCH] = Locale("fr", "CA"); gLocaleCache[eCANADA_FRENCH] = Locale("fr", "CA");
} }
U_CDECL_END } // namespace
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
@ -182,15 +178,8 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) {
canonicalize = true; // always canonicalize host ID canonicalize = true; // always canonicalize host ID
} }
CharString localeNameBuf; CharString localeNameBuf =
{ canonicalize ? ulocimp_canonicalize(id, status) : ulocimp_getName(id, status);
CharStringByteSink sink(&localeNameBuf);
if (canonicalize) {
ulocimp_canonicalize(id, sink, &status);
} else {
ulocimp_getName(id, sink, &status);
}
}
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return gDefaultLocale; return gDefaultLocale;
@ -494,7 +483,7 @@ namespace {
UInitOnce gKnownCanonicalizedInitOnce {}; UInitOnce gKnownCanonicalizedInitOnce {};
UHashtable *gKnownCanonicalized = nullptr; UHashtable *gKnownCanonicalized = nullptr;
static const char* const KNOWN_CANONICALIZED[] = { constexpr const char* KNOWN_CANONICALIZED[] = {
"c", "c",
// Commonly used locales known are already canonicalized // Commonly used locales known are already canonicalized
"af", "af_ZA", "am", "am_ET", "ar", "ar_001", "as", "as_IN", "az", "az_AZ", "af", "af_ZA", "am", "am_ET", "ar", "ar_001", "as", "as_IN", "az", "az_AZ",
@ -518,13 +507,13 @@ static const char* const KNOWN_CANONICALIZED[] = {
"zh_Hant_TW", "zh_TW", "zu", "zu_ZA" "zh_Hant_TW", "zh_TW", "zu", "zu_ZA"
}; };
static UBool U_CALLCONV cleanupKnownCanonicalized() { UBool U_CALLCONV cleanupKnownCanonicalized() {
gKnownCanonicalizedInitOnce.reset(); gKnownCanonicalizedInitOnce.reset();
if (gKnownCanonicalized) { uhash_close(gKnownCanonicalized); } if (gKnownCanonicalized) { uhash_close(gKnownCanonicalized); }
return true; return true;
} }
static void U_CALLCONV loadKnownCanonicalized(UErrorCode &status) { void U_CALLCONV loadKnownCanonicalized(UErrorCode &status) {
ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KNOWN_CANONICALIZED, ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KNOWN_CANONICALIZED,
cleanupKnownCanonicalized); cleanupKnownCanonicalized);
LocalUHashtablePointer newKnownCanonicalizedMap( LocalUHashtablePointer newKnownCanonicalizedMap(
@ -920,6 +909,8 @@ AliasData::loadData(UErrorCode &status)
*/ */
AliasData* AliasData*
AliasDataBuilder::build(UErrorCode &status) { AliasDataBuilder::build(UErrorCode &status) {
if (U_FAILURE(status)) { return nullptr; }
LocalUResourceBundlePointer metadata( LocalUResourceBundlePointer metadata(
ures_openDirect(nullptr, "metadata", &status)); ures_openDirect(nullptr, "metadata", &status));
LocalUResourceBundlePointer metadataAlias( LocalUResourceBundlePointer metadataAlias(
@ -1065,7 +1056,7 @@ AliasDataBuilder::build(UErrorCode &status) {
*/ */
class AliasReplacer { class AliasReplacer {
public: public:
AliasReplacer(UErrorCode status) : AliasReplacer(UErrorCode& status) :
language(nullptr), script(nullptr), region(nullptr), language(nullptr), script(nullptr), region(nullptr),
extensions(nullptr), extensions(nullptr),
// store value in variants only once // store value in variants only once
@ -1130,12 +1121,12 @@ private:
} }
// Gather fields and generate locale ID into out. // Gather fields and generate locale ID into out.
CharString& outputToString(CharString& out, UErrorCode status); CharString& outputToString(CharString& out, UErrorCode& status);
// Generate the lookup key. // Generate the lookup key.
CharString& generateKey(const char* language, const char* region, CharString& generateKey(const char* language, const char* region,
const char* variant, CharString& out, const char* variant, CharString& out,
UErrorCode status); UErrorCode& status);
void parseLanguageReplacement(const char* replacement, void parseLanguageReplacement(const char* replacement,
const char*& replaceLanguage, const char*& replaceLanguage,
@ -1172,8 +1163,9 @@ private:
CharString& CharString&
AliasReplacer::generateKey( AliasReplacer::generateKey(
const char* language, const char* region, const char* variant, const char* language, const char* region, const char* variant,
CharString& out, UErrorCode status) CharString& out, UErrorCode& status)
{ {
if (U_FAILURE(status)) { return out; }
out.append(language, status); out.append(language, status);
if (notEmpty(region)) { if (notEmpty(region)) {
out.append(SEP_CHAR, status) out.append(SEP_CHAR, status)
@ -1529,13 +1521,12 @@ AliasReplacer::replaceTransformedExtensions(
const char* tkey = ultag_getTKeyStart(str); const char* tkey = ultag_getTKeyStart(str);
int32_t tlangLen = (tkey == str) ? 0 : int32_t tlangLen = (tkey == str) ? 0 :
((tkey == nullptr) ? len : static_cast<int32_t>((tkey - str - 1))); ((tkey == nullptr) ? len : static_cast<int32_t>((tkey - str - 1)));
CharStringByteSink sink(&output);
if (tlangLen > 0) { if (tlangLen > 0) {
Locale tlang = LocaleBuilder() Locale tlang = LocaleBuilder()
.setLanguageTag(StringPiece(str, tlangLen)) .setLanguageTag(StringPiece(str, tlangLen))
.build(status); .build(status);
tlang.canonicalize(status); tlang.canonicalize(status);
tlang.toLanguageTag(sink, status); output = tlang.toLanguageTag<CharString>(status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return false; return false;
} }
@ -1591,8 +1582,9 @@ AliasReplacer::replaceTransformedExtensions(
CharString& CharString&
AliasReplacer::outputToString( AliasReplacer::outputToString(
CharString& out, UErrorCode status) CharString& out, UErrorCode& status)
{ {
if (U_FAILURE(status)) { return out; }
out.append(language, status); out.append(language, status);
if (notEmpty(script)) { if (notEmpty(script)) {
out.append(SEP_CHAR, status) out.append(SEP_CHAR, status)
@ -1735,9 +1727,7 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status
while ((key = iter->next(nullptr, status)) != nullptr) { while ((key = iter->next(nullptr, status)) != nullptr) {
if (uprv_strcmp("sd", key) == 0 || uprv_strcmp("rg", key) == 0 || if (uprv_strcmp("sd", key) == 0 || uprv_strcmp("rg", key) == 0 ||
uprv_strcmp("t", key) == 0) { uprv_strcmp("t", key) == 0) {
CharString value; auto value = locale.getKeywordValue<CharString>(key, status);
CharStringByteSink valueSink(&value);
locale.getKeywordValue(key, valueSink, status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
continue; continue;
@ -1782,6 +1772,7 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status
bool bool
canonicalizeLocale(const Locale& locale, CharString& out, UErrorCode& status) canonicalizeLocale(const Locale& locale, CharString& out, UErrorCode& status)
{ {
if (U_FAILURE(status)) { return false; }
AliasReplacer replacer(status); AliasReplacer replacer(status);
return replacer.replace(locale, out, status); return replacer.replace(locale, out, status);
} }
@ -1791,6 +1782,8 @@ canonicalizeLocale(const Locale& locale, CharString& out, UErrorCode& status)
bool bool
isKnownCanonicalizedLocale(const char* locale, UErrorCode& status) isKnownCanonicalizedLocale(const char* locale, UErrorCode& status)
{ {
if (U_FAILURE(status)) { return false; }
if ( uprv_strcmp(locale, "c") == 0 || if ( uprv_strcmp(locale, "c") == 0 ||
uprv_strcmp(locale, "en") == 0 || uprv_strcmp(locale, "en") == 0 ||
uprv_strcmp(locale, "en_US") == 0) { uprv_strcmp(locale, "en_US") == 0) {
@ -1809,24 +1802,30 @@ isKnownCanonicalizedLocale(const char* locale, UErrorCode& status)
} // namespace } // namespace
U_NAMESPACE_END
// Function for testing. // Function for testing.
U_CAPI const char* const* U_EXPORT const char* const*
ulocimp_getKnownCanonicalizedLocaleForTest(int32_t* length) ulocimp_getKnownCanonicalizedLocaleForTest(int32_t& length)
{ {
*length = UPRV_LENGTHOF(KNOWN_CANONICALIZED); U_NAMESPACE_USE
length = UPRV_LENGTHOF(KNOWN_CANONICALIZED);
return KNOWN_CANONICALIZED; return KNOWN_CANONICALIZED;
} }
// Function for testing. // Function for testing.
U_CAPI bool U_EXPORT bool
ulocimp_isCanonicalizedLocaleForTest(const char* localeName) ulocimp_isCanonicalizedLocaleForTest(const char* localeName)
{ {
U_NAMESPACE_USE
Locale l(localeName); Locale l(localeName);
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
CharString temp; CharString temp;
return !canonicalizeLocale(l, temp, status) && U_SUCCESS(status); return !canonicalizeLocale(l, temp, status) && U_SUCCESS(status);
} }
U_NAMESPACE_BEGIN
/*This function initializes a Locale from a C locale ID*/ /*This function initializes a Locale from a C locale ID*/
Locale& Locale::init(const char* localeID, UBool canonicalize) Locale& Locale::init(const char* localeID, UBool canonicalize)
{ {
@ -1846,7 +1845,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize)
// without goto and without another function // without goto and without another function
do { do {
char *separator; char *separator;
char *field[5] = {0}; char *field[5] = {nullptr};
int32_t fieldLen[5] = {0}; int32_t fieldLen[5] = {0};
int32_t fieldIdx; int32_t fieldIdx;
int32_t variantField; int32_t variantField;
@ -1871,7 +1870,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize)
U_ASSERT(baseName == nullptr); U_ASSERT(baseName == nullptr);
/*Go to heap for the fullName if necessary*/ /*Go to heap for the fullName if necessary*/
fullName = (char *)uprv_malloc(sizeof(char)*(length + 1)); fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
if(fullName == 0) { if (fullName == nullptr) {
fullName = fullNameBuffer; fullName = fullNameBuffer;
break; // error: out of memory break; // error: out of memory
} }
@ -1892,7 +1891,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize)
separator = field[0] = fullName; separator = field[0] = fullName;
fieldIdx = 1; fieldIdx = 1;
char* at = uprv_strchr(fullName, '@'); char* at = uprv_strchr(fullName, '@');
while ((separator = uprv_strchr(field[fieldIdx-1], SEP_CHAR)) != 0 && while ((separator = uprv_strchr(field[fieldIdx-1], SEP_CHAR)) != nullptr &&
fieldIdx < UPRV_LENGTHOF(field)-1 && fieldIdx < UPRV_LENGTHOF(field)-1 &&
(at == nullptr || separator < at)) { (at == nullptr || separator < at)) {
field[fieldIdx] = separator + 1; field[fieldIdx] = separator + 1;
@ -2074,11 +2073,7 @@ Locale::addLikelySubtags(UErrorCode& status) {
return; return;
} }
CharString maximizedLocaleID; CharString maximizedLocaleID = ulocimp_addLikelySubtags(fullName, status);
{
CharStringByteSink sink(&maximizedLocaleID);
ulocimp_addLikelySubtags(fullName, sink, &status);
}
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return; return;
@ -2100,11 +2095,7 @@ Locale::minimizeSubtags(bool favorScript, UErrorCode& status) {
return; return;
} }
CharString minimizedLocaleID; CharString minimizedLocaleID = ulocimp_minimizeSubtags(fullName, favorScript, status);
{
CharStringByteSink sink(&minimizedLocaleID);
ulocimp_minimizeSubtags(fullName, sink, favorScript, &status);
}
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return; return;
@ -2155,17 +2146,12 @@ Locale::forLanguageTag(StringPiece tag, UErrorCode& status)
// parsing. Therefore the code here explicitly calls uloc_forLanguageTag() // parsing. Therefore the code here explicitly calls uloc_forLanguageTag()
// and then Locale::init(), instead of just calling the normal constructor. // and then Locale::init(), instead of just calling the normal constructor.
CharString localeID;
int32_t parsedLength; int32_t parsedLength;
{ CharString localeID = ulocimp_forLanguageTag(
CharStringByteSink sink(&localeID);
ulocimp_forLanguageTag(
tag.data(), tag.data(),
tag.length(), tag.length(),
sink,
&parsedLength, &parsedLength,
&status); status);
}
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return result; return result;
@ -2195,7 +2181,7 @@ Locale::toLanguageTag(ByteSink& sink, UErrorCode& status) const
return; return;
} }
ulocimp_toLanguageTag(fullName, sink, /*strict=*/false, &status); ulocimp_toLanguageTag(fullName, sink, /*strict=*/false, status);
} }
Locale U_EXPORT2 Locale U_EXPORT2
@ -2420,33 +2406,23 @@ Locale::getLocaleCache()
class KeywordEnumeration : public StringEnumeration { class KeywordEnumeration : public StringEnumeration {
protected: protected:
char *keywords; CharString keywords;
private: private:
char *current; const char *current;
int32_t length; static const char fgClassID;
UnicodeString currUSKey;
static const char fgClassID;/* Warning this is used beyond the typical RTTI usage. */
public: public:
static UClassID U_EXPORT2 getStaticClassID() { return (UClassID)&fgClassID; } static UClassID U_EXPORT2 getStaticClassID() { return (UClassID)&fgClassID; }
virtual UClassID getDynamicClassID() const override { return getStaticClassID(); } virtual UClassID getDynamicClassID() const override { return getStaticClassID(); }
public: public:
KeywordEnumeration(const char *keys, int32_t keywordLen, int32_t currentIndex, UErrorCode &status) KeywordEnumeration(const char *keys, int32_t keywordLen, int32_t currentIndex, UErrorCode &status)
: keywords((char *)&fgClassID), current((char *)&fgClassID), length(0) { : keywords(), current(keywords.data()) {
if(U_SUCCESS(status) && keywordLen != 0) { if(U_SUCCESS(status) && keywordLen != 0) {
if(keys == nullptr || keywordLen < 0) { if(keys == nullptr || keywordLen < 0) {
status = U_ILLEGAL_ARGUMENT_ERROR; status = U_ILLEGAL_ARGUMENT_ERROR;
} else { } else {
keywords = (char *)uprv_malloc(keywordLen+1); keywords.append(keys, keywordLen, status);
if (keywords == nullptr) { current = keywords.data() + currentIndex;
status = U_MEMORY_ALLOCATION_ERROR;
}
else {
uprv_memcpy(keywords, keys, keywordLen);
keywords[keywordLen] = 0;
current = keywords + currentIndex;
length = keywordLen;
}
} }
} }
} }
@ -2456,11 +2432,14 @@ public:
virtual StringEnumeration * clone() const override virtual StringEnumeration * clone() const override
{ {
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
return new KeywordEnumeration(keywords, length, (int32_t)(current - keywords), status); return new KeywordEnumeration(
keywords.data(), keywords.length(),
(int32_t)(current - keywords.data()), status);
} }
virtual int32_t count(UErrorCode &/*status*/) const override { virtual int32_t count(UErrorCode& status) const override {
char *kw = keywords; if (U_FAILURE(status)) { return 0; }
const char *kw = keywords.data();
int32_t result = 0; int32_t result = 0;
while(*kw) { while(*kw) {
result++; result++;
@ -2489,21 +2468,22 @@ public:
} }
virtual const UnicodeString* snext(UErrorCode& status) override { virtual const UnicodeString* snext(UErrorCode& status) override {
if (U_FAILURE(status)) { return nullptr; }
int32_t resultLength = 0; int32_t resultLength = 0;
const char *s = next(&resultLength, status); const char *s = next(&resultLength, status);
return setChars(s, resultLength, status); return setChars(s, resultLength, status);
} }
virtual void reset(UErrorCode& /*status*/) override { virtual void reset(UErrorCode& status) override {
current = keywords; if (U_FAILURE(status)) { return; }
current = keywords.data();
} }
}; };
const char KeywordEnumeration::fgClassID = '\0'; const char KeywordEnumeration::fgClassID = '\0';
KeywordEnumeration::~KeywordEnumeration() { // Out-of-line virtual destructor to serve as the "key function".
uprv_free(keywords); KeywordEnumeration::~KeywordEnumeration() = default;
}
// A wrapper around KeywordEnumeration that calls uloc_toUnicodeLocaleKey() in // A wrapper around KeywordEnumeration that calls uloc_toUnicodeLocaleKey() in
// the next() method for each keyword before returning it. // the next() method for each keyword before returning it.
@ -2528,8 +2508,9 @@ public:
if (resultLength != nullptr) *resultLength = 0; if (resultLength != nullptr) *resultLength = 0;
return nullptr; return nullptr;
} }
virtual int32_t count(UErrorCode &/*status*/) const override { virtual int32_t count(UErrorCode& status) const override {
char *kw = keywords; if (U_FAILURE(status)) { return 0; }
const char *kw = keywords.data();
int32_t result = 0; int32_t result = 0;
while(*kw) { while(*kw) {
if (uloc_toUnicodeLocaleKey(kw) != nullptr) { if (uloc_toUnicodeLocaleKey(kw) != nullptr) {
@ -2557,9 +2538,7 @@ Locale::createKeywords(UErrorCode &status) const
const char* assignment = uprv_strchr(fullName, '='); const char* assignment = uprv_strchr(fullName, '=');
if(variantStart) { if(variantStart) {
if(assignment > variantStart) { if(assignment > variantStart) {
CharString keywords; CharString keywords = ulocimp_getKeywords(variantStart + 1, '@', false, status);
CharStringByteSink sink(&keywords);
ulocimp_getKeywords(variantStart+1, '@', sink, false, &status);
if (U_SUCCESS(status) && !keywords.isEmpty()) { if (U_SUCCESS(status) && !keywords.isEmpty()) {
result = new KeywordEnumeration(keywords.data(), keywords.length(), 0, status); result = new KeywordEnumeration(keywords.data(), keywords.length(), 0, status);
if (!result) { if (!result) {
@ -2586,9 +2565,7 @@ Locale::createUnicodeKeywords(UErrorCode &status) const
const char* assignment = uprv_strchr(fullName, '='); const char* assignment = uprv_strchr(fullName, '=');
if(variantStart) { if(variantStart) {
if(assignment > variantStart) { if(assignment > variantStart) {
CharString keywords; CharString keywords = ulocimp_getKeywords(variantStart + 1, '@', false, status);
CharStringByteSink sink(&keywords);
ulocimp_getKeywords(variantStart+1, '@', sink, false, &status);
if (U_SUCCESS(status) && !keywords.isEmpty()) { if (U_SUCCESS(status) && !keywords.isEmpty()) {
result = new UnicodeKeywordEnumeration(keywords.data(), keywords.length(), 0, status); result = new UnicodeKeywordEnumeration(keywords.data(), keywords.length(), 0, status);
if (!result) { if (!result) {
@ -2625,13 +2602,17 @@ Locale::getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& sta
return; return;
} }
ulocimp_getKeywordValue(fullName, keywordName_nul.data(), sink, &status); ulocimp_getKeywordValue(fullName, keywordName_nul.data(), sink, status);
} }
void void
Locale::getUnicodeKeywordValue(StringPiece keywordName, Locale::getUnicodeKeywordValue(StringPiece keywordName,
ByteSink& sink, ByteSink& sink,
UErrorCode& status) const { UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
// TODO: Remove the need for a const char* to a NUL terminated buffer. // TODO: Remove the need for a const char* to a NUL terminated buffer.
const CharString keywordName_nul(keywordName, status); const CharString keywordName_nul(keywordName, status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
@ -2639,17 +2620,12 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName,
} }
const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data());
if (legacy_key == nullptr) { if (legacy_key == nullptr) {
status = U_ILLEGAL_ARGUMENT_ERROR; status = U_ILLEGAL_ARGUMENT_ERROR;
return; return;
} }
CharString legacy_value; auto legacy_value = getKeywordValue<CharString>(legacy_key, status);
{
CharStringByteSink sink(&legacy_value);
getKeywordValue(legacy_key, sink, status);
}
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return; return;
@ -2712,6 +2688,7 @@ void
Locale::setKeywordValue(StringPiece keywordName, Locale::setKeywordValue(StringPiece keywordName,
StringPiece keywordValue, StringPiece keywordValue,
UErrorCode& status) { UErrorCode& status) {
if (U_FAILURE(status)) { return; }
// TODO: Remove the need for a const char* to a NUL terminated buffer. // TODO: Remove the need for a const char* to a NUL terminated buffer.
const CharString keywordName_nul(keywordName, status); const CharString keywordName_nul(keywordName, status);
const CharString keywordValue_nul(keywordValue, status); const CharString keywordValue_nul(keywordValue, status);
@ -2722,16 +2699,18 @@ void
Locale::setUnicodeKeywordValue(StringPiece keywordName, Locale::setUnicodeKeywordValue(StringPiece keywordName,
StringPiece keywordValue, StringPiece keywordValue,
UErrorCode& status) { UErrorCode& status) {
if (U_FAILURE(status)) {
return;
}
// TODO: Remove the need for a const char* to a NUL terminated buffer. // TODO: Remove the need for a const char* to a NUL terminated buffer.
const CharString keywordName_nul(keywordName, status); const CharString keywordName_nul(keywordName, status);
const CharString keywordValue_nul(keywordValue, status); const CharString keywordValue_nul(keywordValue, status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return; return;
} }
const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data());
if (legacy_key == nullptr) { if (legacy_key == nullptr) {
status = U_ILLEGAL_ARGUMENT_ERROR; status = U_ILLEGAL_ARGUMENT_ERROR;
return; return;

View File

@ -19,6 +19,8 @@
* that then do not depend on resource bundle code and likely-subtags data. * that then do not depend on resource bundle code and likely-subtags data.
*/ */
#include <utility>
#include "unicode/bytestream.h" #include "unicode/bytestream.h"
#include "unicode/utypes.h" #include "unicode/utypes.h"
#include "unicode/locid.h" #include "unicode/locid.h"
@ -33,72 +35,31 @@
#include "cstring.h" #include "cstring.h"
#include "loclikelysubtags.h" #include "loclikelysubtags.h"
#include "ulocimp.h" #include "ulocimp.h"
#include "ustr_imp.h"
/** namespace {
* Append a tag to a buffer, adding the separator if necessary. The buffer
* must be large enough to contain the resulting tag plus any separator
* necessary. The tag must not be a zero-length string.
*
* @param tag The tag to add.
* @param tagLength The length of the tag.
* @param buffer The output buffer.
* @param bufferLength The length of the output buffer. This is an input/output parameter.
**/
static void U_CALLCONV
appendTag(
const char* tag,
int32_t tagLength,
char* buffer,
int32_t* bufferLength,
UBool withSeparator) {
if (withSeparator) {
buffer[*bufferLength] = '_';
++(*bufferLength);
}
uprv_memmove(
&buffer[*bufferLength],
tag,
tagLength);
*bufferLength += tagLength;
}
/** /**
* Create a tag string from the supplied parameters. The lang, script and region * Create a tag string from the supplied parameters. The lang, script and region
* parameters may be nullptr pointers. If they are, their corresponding length parameters * parameters may be nullptr pointers. If they are, their corresponding length parameters
* must be less than or equal to 0. * must be less than or equal to 0.
* *
* If any of the language, script or region parameters are empty, and the alternateTags
* parameter is not nullptr, it will be parsed for potential language, script and region tags
* to be used when constructing the new tag. If the alternateTags parameter is nullptr, or
* it contains no language tag, the default tag for the unknown language is used.
*
* If the length of the new string exceeds the capacity of the output buffer,
* the function copies as many bytes to the output buffer as it can, and returns
* the error U_BUFFER_OVERFLOW_ERROR.
*
* If an illegal argument is provided, the function returns the error * If an illegal argument is provided, the function returns the error
* U_ILLEGAL_ARGUMENT_ERROR. * U_ILLEGAL_ARGUMENT_ERROR.
* *
* Note that this function can return the warning U_STRING_NOT_TERMINATED_WARNING if
* the tag string fits in the output buffer, but the null terminator doesn't.
*
* @param lang The language tag to use. * @param lang The language tag to use.
* @param langLength The length of the language tag. * @param langLength The length of the language tag.
* @param script The script tag to use. * @param script The script tag to use.
* @param scriptLength The length of the script tag. * @param scriptLength The length of the script tag.
* @param region The region tag to use. * @param region The region tag to use.
* @param regionLength The length of the region tag. * @param regionLength The length of the region tag.
* @param variant The region tag to use.
* @param variantLength The length of the region tag.
* @param trailing Any trailing data to append to the new tag. * @param trailing Any trailing data to append to the new tag.
* @param trailingLength The length of the trailing data. * @param trailingLength The length of the trailing data.
* @param alternateTags A string containing any alternate tags.
* @param sink The output sink receiving the tag string. * @param sink The output sink receiving the tag string.
* @param err A pointer to a UErrorCode for error reporting. * @param err A pointer to a UErrorCode for error reporting.
**/ **/
static void U_CALLCONV void U_CALLCONV
createTagStringWithAlternates( createTagStringWithAlternates(
const char* lang, const char* lang,
int32_t langLength, int32_t langLength,
@ -106,392 +67,125 @@ createTagStringWithAlternates(
int32_t scriptLength, int32_t scriptLength,
const char* region, const char* region,
int32_t regionLength, int32_t regionLength,
const char* variant,
int32_t variantLength,
const char* trailing, const char* trailing,
int32_t trailingLength, int32_t trailingLength,
const char* alternateTags,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* err) { UErrorCode& err) {
if (U_FAILURE(err)) {
if (U_FAILURE(*err)) { return;
goto error;
} }
else if (langLength >= ULOC_LANG_CAPACITY ||
if (langLength >= ULOC_LANG_CAPACITY ||
scriptLength >= ULOC_SCRIPT_CAPACITY || scriptLength >= ULOC_SCRIPT_CAPACITY ||
regionLength >= ULOC_COUNTRY_CAPACITY) { regionLength >= ULOC_COUNTRY_CAPACITY) {
goto error; err = U_ILLEGAL_ARGUMENT_ERROR;
return;
} }
else {
/**
* ULOC_FULLNAME_CAPACITY will provide enough capacity
* that we can build a string that contains the language,
* script and region code without worrying about overrunning
* the user-supplied buffer.
**/
char tagBuffer[ULOC_FULLNAME_CAPACITY];
int32_t tagLength = 0;
UBool regionAppended = false;
if (langLength > 0) { if (langLength > 0) {
appendTag( sink.Append(lang, langLength);
lang,
langLength,
tagBuffer,
&tagLength,
/*withSeparator=*/false);
}
else if (alternateTags == nullptr) {
/*
* Use the empty string for an unknown language, if
* we found no language.
*/
}
else {
/*
* Parse the alternateTags string for the language.
*/
char alternateLang[ULOC_LANG_CAPACITY];
int32_t alternateLangLength = sizeof(alternateLang);
alternateLangLength =
uloc_getLanguage(
alternateTags,
alternateLang,
alternateLangLength,
err);
if(U_FAILURE(*err) ||
alternateLangLength >= ULOC_LANG_CAPACITY) {
goto error;
}
else if (alternateLangLength == 0) {
/*
* Use the empty string for an unknown language, if
* we found no language.
*/
}
else {
appendTag(
alternateLang,
alternateLangLength,
tagBuffer,
&tagLength,
/*withSeparator=*/false);
}
} }
if (scriptLength > 0) { if (scriptLength > 0) {
appendTag( sink.Append("_", 1);
script, sink.Append(script, scriptLength);
scriptLength,
tagBuffer,
&tagLength,
/*withSeparator=*/true);
}
else if (alternateTags != nullptr) {
/*
* Parse the alternateTags string for the script.
*/
char alternateScript[ULOC_SCRIPT_CAPACITY];
const int32_t alternateScriptLength =
uloc_getScript(
alternateTags,
alternateScript,
sizeof(alternateScript),
err);
if (U_FAILURE(*err) ||
alternateScriptLength >= ULOC_SCRIPT_CAPACITY) {
goto error;
}
else if (alternateScriptLength > 0) {
appendTag(
alternateScript,
alternateScriptLength,
tagBuffer,
&tagLength,
/*withSeparator=*/true);
}
} }
if (regionLength > 0) { if (regionLength > 0) {
appendTag(
region,
regionLength,
tagBuffer,
&tagLength,
/*withSeparator=*/true);
regionAppended = true;
}
else if (alternateTags != nullptr) {
/*
* Parse the alternateTags string for the region.
*/
char alternateRegion[ULOC_COUNTRY_CAPACITY];
const int32_t alternateRegionLength =
uloc_getCountry(
alternateTags,
alternateRegion,
sizeof(alternateRegion),
err);
if (U_FAILURE(*err) ||
alternateRegionLength >= ULOC_COUNTRY_CAPACITY) {
goto error;
}
else if (alternateRegionLength > 0) {
appendTag(
alternateRegion,
alternateRegionLength,
tagBuffer,
&tagLength,
/*withSeparator=*/true);
regionAppended = true;
}
}
/**
* Copy the partial tag from our internal buffer to the supplied
* target.
**/
sink.Append(tagBuffer, tagLength);
if (trailingLength > 0) {
if (*trailing != '@') {
sink.Append("_", 1); sink.Append("_", 1);
if (!regionAppended) { sink.Append(region, regionLength);
}
if (variantLength > 0) {
if (regionLength == 0) {
/* extra separator is required */ /* extra separator is required */
sink.Append("_", 1); sink.Append("_", 1);
} }
sink.Append("_", 1);
sink.Append(variant, variantLength);
} }
if (trailingLength > 0) {
/* /*
* Copy the trailing data into the supplied buffer. * Copy the trailing data into the supplied buffer.
*/ */
sink.Append(trailing, trailingLength); sink.Append(trailing, trailingLength);
} }
}
bool CHECK_TRAILING_VARIANT_SIZE(const char* variant, int32_t variantLength) {
int32_t count = 0;
for (int32_t i = 0; i < variantLength; i++) {
if (_isIDSeparator(variant[i])) {
count = 0;
} else if (count == 8) {
return false;
} else {
count++;
}
}
return true;
}
void
_uloc_addLikelySubtags(const char* localeID,
icu::ByteSink& sink,
UErrorCode& err) {
if (U_FAILURE(err)) {
return; return;
} }
error:
/**
* An overflow indicates the locale ID passed in
* is ill-formed. If we got here, and there was
* no previous error, it's an implicit overflow.
**/
if (*err == U_BUFFER_OVERFLOW_ERROR ||
U_SUCCESS(*err)) {
*err = U_ILLEGAL_ARGUMENT_ERROR;
}
}
/**
* Parse the language, script, and region subtags from a tag string, and copy the
* results into the corresponding output parameters. The buffers are null-terminated,
* unless overflow occurs.
*
* The langLength, scriptLength, and regionLength parameters are input/output
* parameters, and must contain the capacity of their corresponding buffers on
* input. On output, they will contain the actual length of the buffers, not
* including the null terminator.
*
* If the length of any of the output subtags exceeds the capacity of the corresponding
* buffer, the function copies as many bytes to the output buffer as it can, and returns
* the error U_BUFFER_OVERFLOW_ERROR. It will not parse any more subtags once overflow
* occurs.
*
* If an illegal argument is provided, the function returns the error
* U_ILLEGAL_ARGUMENT_ERROR.
*
* @param localeID The locale ID to parse.
* @param lang The language tag buffer.
* @param langLength The length of the language tag.
* @param script The script tag buffer.
* @param scriptLength The length of the script tag.
* @param region The region tag buffer.
* @param regionLength The length of the region tag.
* @param err A pointer to a UErrorCode for error reporting.
* @return The number of chars of the localeID parameter consumed.
**/
static int32_t U_CALLCONV
parseTagString(
const char* localeID,
char* lang,
int32_t* langLength,
char* script,
int32_t* scriptLength,
char* region,
int32_t* regionLength,
UErrorCode* err)
{
const char* position = localeID;
int32_t subtagLength = 0;
if(U_FAILURE(*err) ||
localeID == nullptr ||
lang == nullptr ||
langLength == nullptr ||
script == nullptr ||
scriptLength == nullptr ||
region == nullptr ||
regionLength == nullptr) {
goto error;
}
subtagLength = ulocimp_getLanguage(position, &position, *err).extract(lang, *langLength, *err);
/*
* Note that we explicit consider U_STRING_NOT_TERMINATED_WARNING
* to be an error, because it indicates the user-supplied tag is
* not well-formed.
*/
if(U_FAILURE(*err)) {
goto error;
}
*langLength = subtagLength;
/*
* If no language was present, use the empty string instead.
* Otherwise, move past any separator.
*/
if (_isIDSeparator(*position)) {
++position;
}
subtagLength = ulocimp_getScript(position, &position, *err).extract(script, *scriptLength, *err);
if(U_FAILURE(*err)) {
goto error;
}
*scriptLength = subtagLength;
if (*scriptLength > 0) {
/*
* Move past any separator.
*/
if (_isIDSeparator(*position)) {
++position;
}
}
subtagLength = ulocimp_getCountry(position, &position, *err).extract(region, *regionLength, *err);
if(U_FAILURE(*err)) {
goto error;
}
*regionLength = subtagLength;
if (*regionLength <= 0 && *position != 0 && *position != '@') {
/* back up over consumed trailing separator */
--position;
}
exit:
return (int32_t)(position - localeID);
error:
/**
* If we get here, we have no explicit error, it's the result of an
* illegal argument.
**/
if (!U_FAILURE(*err)) {
*err = U_ILLEGAL_ARGUMENT_ERROR;
}
goto exit;
}
#define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) UPRV_BLOCK_MACRO_BEGIN { \
int32_t count = 0; \
int32_t i; \
for (i = 0; i < trailingLength; i++) { \
if (trailing[i] == '-' || trailing[i] == '_') { \
count = 0; \
if (count > 8) { \
goto error; \
} \
} else if (trailing[i] == '@') { \
break; \
} else if (count > 8) { \
goto error; \
} else { \
count++; \
} \
} \
} UPRV_BLOCK_MACRO_END
static UBool
_uloc_addLikelySubtags(const char* localeID,
icu::ByteSink& sink,
UErrorCode* err) {
char lang[ULOC_LANG_CAPACITY];
int32_t langLength = sizeof(lang);
char script[ULOC_SCRIPT_CAPACITY];
int32_t scriptLength = sizeof(script);
char region[ULOC_COUNTRY_CAPACITY];
int32_t regionLength = sizeof(region);
const char* trailing = "";
int32_t trailingLength = 0;
int32_t trailingIndex = 0;
if(U_FAILURE(*err)) {
goto error;
}
if (localeID == nullptr) { if (localeID == nullptr) {
goto error; err = U_ILLEGAL_ARGUMENT_ERROR;
return;
} }
trailingIndex = parseTagString( icu::CharString lang;
localeID, icu::CharString script;
lang, icu::CharString region;
&langLength, icu::CharString variant;
script, const char* trailing = nullptr;
&scriptLength, ulocimp_getSubtags(localeID, &lang, &script, &region, &variant, &trailing, err);
region, if (U_FAILURE(err)) {
&regionLength, return;
err);
if(U_FAILURE(*err)) {
/* Overflow indicates an illegal argument error */
if (*err == U_BUFFER_OVERFLOW_ERROR) {
*err = U_ILLEGAL_ARGUMENT_ERROR;
} }
goto error; if (!CHECK_TRAILING_VARIANT_SIZE(variant.data(), variant.length())) {
} err = U_ILLEGAL_ARGUMENT_ERROR;
if (langLength > 3) { return;
goto error;
} }
/* Find the length of the trailing portion. */ if (lang.length() == 4) {
while (_isIDSeparator(localeID[trailingIndex])) { if (script.isEmpty()) {
trailingIndex++; script = std::move(lang);
lang.clear();
} else {
err = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
} else if (lang.length() > 8) {
err = U_ILLEGAL_ARGUMENT_ERROR;
return;
} }
trailing = &localeID[trailingIndex];
trailingLength = (int32_t)uprv_strlen(trailing);
CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); int32_t trailingLength = (int32_t)uprv_strlen(trailing);
{
const icu::XLikelySubtags* likelySubtags = icu::XLikelySubtags::getSingleton(*err); const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err);
if(U_FAILURE(*err)) { if (U_FAILURE(err)) {
goto error; return;
} }
// We need to keep l on the stack because lsr may point into internal // We need to keep l on the stack because lsr may point into internal
// memory of l. // memory of l.
icu::Locale l = icu::Locale::createFromName(localeID); icu::Locale l = icu::Locale::createFromName(localeID);
if (l.isBogus()) { if (l.isBogus()) {
goto error; err = U_ILLEGAL_ARGUMENT_ERROR;
return;
} }
icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, *err); icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, err);
if(U_FAILURE(*err)) { if (U_FAILURE(err)) {
goto error; return;
} }
const char* language = lsr.language; const char* language = lsr.language;
if (uprv_strcmp(language, "und") == 0) { if (uprv_strcmp(language, "und") == 0) {
@ -504,97 +198,57 @@ _uloc_addLikelySubtags(const char* localeID,
(int32_t)uprv_strlen(lsr.script), (int32_t)uprv_strlen(lsr.script),
lsr.region, lsr.region,
(int32_t)uprv_strlen(lsr.region), (int32_t)uprv_strlen(lsr.region),
variant.data(),
variant.length(),
trailing, trailing,
trailingLength, trailingLength,
nullptr,
sink, sink,
err); err);
if(U_FAILURE(*err)) {
goto error;
}
}
return true;
error:
if (!U_FAILURE(*err)) {
*err = U_ILLEGAL_ARGUMENT_ERROR;
}
return false;
} }
// Add likely subtags to the sink void
// return true if the value in the sink is produced by a match during the lookup
// return false if the value in the sink is the same as input because there are
// no match after the lookup.
static UBool _ulocimp_addLikelySubtags(const char*, icu::ByteSink&, UErrorCode*);
static void
_uloc_minimizeSubtags(const char* localeID, _uloc_minimizeSubtags(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
bool favorScript, bool favorScript,
UErrorCode* err) { UErrorCode& err) {
icu::CharString maximizedTagBuffer; if (U_FAILURE(err)) {
return;
char lang[ULOC_LANG_CAPACITY];
int32_t langLength = sizeof(lang);
char script[ULOC_SCRIPT_CAPACITY];
int32_t scriptLength = sizeof(script);
char region[ULOC_COUNTRY_CAPACITY];
int32_t regionLength = sizeof(region);
const char* trailing = "";
int32_t trailingLength = 0;
int32_t trailingIndex = 0;
if(U_FAILURE(*err)) {
goto error;
}
else if (localeID == nullptr) {
goto error;
} }
trailingIndex = if (localeID == nullptr) {
parseTagString( err = U_ILLEGAL_ARGUMENT_ERROR;
localeID, return;
lang,
&langLength,
script,
&scriptLength,
region,
&regionLength,
err);
if(U_FAILURE(*err)) {
/* Overflow indicates an illegal argument error */
if (*err == U_BUFFER_OVERFLOW_ERROR) {
*err = U_ILLEGAL_ARGUMENT_ERROR;
} }
goto error; icu::CharString lang;
icu::CharString script;
icu::CharString region;
icu::CharString variant;
const char* trailing = nullptr;
ulocimp_getSubtags(localeID, &lang, &script, &region, &variant, &trailing, err);
if (U_FAILURE(err)) {
return;
} }
/* Find the spot where the variants or the keywords begin, if any. */ if (!CHECK_TRAILING_VARIANT_SIZE(variant.data(), variant.length())) {
while (_isIDSeparator(localeID[trailingIndex])) { err = U_ILLEGAL_ARGUMENT_ERROR;
trailingIndex++; return;
} }
trailing = &localeID[trailingIndex];
trailingLength = (int32_t)uprv_strlen(trailing);
CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); int32_t trailingLength = (int32_t)uprv_strlen(trailing);
{ const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err);
const icu::XLikelySubtags* likelySubtags = icu::XLikelySubtags::getSingleton(*err); if (U_FAILURE(err)) {
if(U_FAILURE(*err)) { return;
goto error;
} }
icu::LSR lsr = likelySubtags->minimizeSubtags( icu::LSR lsr = likelySubtags->minimizeSubtags(
{lang, langLength}, lang.toStringPiece(),
{script, scriptLength}, script.toStringPiece(),
{region, regionLength}, region.toStringPiece(),
favorScript, favorScript,
*err); err);
if(U_FAILURE(*err)) { if (U_FAILURE(err)) {
goto error; return;
} }
const char* language = lsr.language; const char* language = lsr.language;
if (uprv_strcmp(language, "und") == 0) { if (uprv_strcmp(language, "und") == 0) {
@ -607,74 +261,46 @@ _uloc_minimizeSubtags(const char* localeID,
(int32_t)uprv_strlen(lsr.script), (int32_t)uprv_strlen(lsr.script),
lsr.region, lsr.region,
(int32_t)uprv_strlen(lsr.region), (int32_t)uprv_strlen(lsr.region),
variant.data(),
variant.length(),
trailing, trailing,
trailingLength, trailingLength,
nullptr,
sink, sink,
err); err);
if(U_FAILURE(*err)) {
goto error;
}
return;
}
error:
if (!U_FAILURE(*err)) {
*err = U_ILLEGAL_ARGUMENT_ERROR;
}
} }
} // namespace
U_CAPI int32_t U_EXPORT2 U_CAPI int32_t U_EXPORT2
uloc_addLikelySubtags(const char* localeID, uloc_addLikelySubtags(const char* localeID,
char* maximizedLocaleID, char* maximizedLocaleID,
int32_t maximizedLocaleIDCapacity, int32_t maximizedLocaleIDCapacity,
UErrorCode* status) { UErrorCode* status) {
if (U_FAILURE(*status)) { return icu::ByteSinkUtil::viaByteSinkToTerminatedChars(
return 0; maximizedLocaleID, maximizedLocaleIDCapacity,
} [&](icu::ByteSink& sink, UErrorCode& status) {
icu::CheckedArrayByteSink sink(
maximizedLocaleID, maximizedLocaleIDCapacity);
ulocimp_addLikelySubtags(localeID, sink, status); ulocimp_addLikelySubtags(localeID, sink, status);
int32_t reslen = sink.NumberOfBytesAppended(); },
*status);
if (U_FAILURE(*status)) {
return sink.Overflowed() ? reslen : -1;
}
if (sink.Overflowed()) {
*status = U_BUFFER_OVERFLOW_ERROR;
} else {
u_terminateChars(
maximizedLocaleID, maximizedLocaleIDCapacity, reslen, status);
}
return reslen;
} }
static UBool U_EXPORT icu::CharString
_ulocimp_addLikelySubtags(const char* localeID, ulocimp_addLikelySubtags(const char* localeID,
icu::ByteSink& sink, UErrorCode& status) {
UErrorCode* status) { return icu::ByteSinkUtil::viaByteSinkToCharString(
icu::CharString localeBuffer; [&](icu::ByteSink& sink, UErrorCode& status) {
{ ulocimp_addLikelySubtags(localeID, sink, status);
icu::CharStringByteSink localeSink(&localeBuffer); },
ulocimp_canonicalize(localeID, localeSink, status); status);
}
if (U_SUCCESS(*status)) {
return _uloc_addLikelySubtags(localeBuffer.data(), sink, status);
} else {
return false;
}
} }
U_CAPI void U_EXPORT2 U_EXPORT void
ulocimp_addLikelySubtags(const char* localeID, ulocimp_addLikelySubtags(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* status) { UErrorCode& status) {
_ulocimp_addLikelySubtags(localeID, sink, status); if (U_FAILURE(status)) { return; }
icu::CharString localeBuffer = ulocimp_canonicalize(localeID, status);
_uloc_addLikelySubtags(localeBuffer.data(), sink, status);
} }
U_CAPI int32_t U_EXPORT2 U_CAPI int32_t U_EXPORT2
@ -682,40 +308,32 @@ uloc_minimizeSubtags(const char* localeID,
char* minimizedLocaleID, char* minimizedLocaleID,
int32_t minimizedLocaleIDCapacity, int32_t minimizedLocaleIDCapacity,
UErrorCode* status) { UErrorCode* status) {
if (U_FAILURE(*status)) { return icu::ByteSinkUtil::viaByteSinkToTerminatedChars(
return 0; minimizedLocaleID, minimizedLocaleIDCapacity,
} [&](icu::ByteSink& sink, UErrorCode& status) {
icu::CheckedArrayByteSink sink(
minimizedLocaleID, minimizedLocaleIDCapacity);
ulocimp_minimizeSubtags(localeID, sink, false, status); ulocimp_minimizeSubtags(localeID, sink, false, status);
int32_t reslen = sink.NumberOfBytesAppended(); },
*status);
if (U_FAILURE(*status)) {
return sink.Overflowed() ? reslen : -1;
}
if (sink.Overflowed()) {
*status = U_BUFFER_OVERFLOW_ERROR;
} else {
u_terminateChars(
minimizedLocaleID, minimizedLocaleIDCapacity, reslen, status);
}
return reslen;
} }
U_CAPI void U_EXPORT2 U_EXPORT icu::CharString
ulocimp_minimizeSubtags(const char* localeID,
bool favorScript,
UErrorCode& status) {
return icu::ByteSinkUtil::viaByteSinkToCharString(
[&](icu::ByteSink& sink, UErrorCode& status) {
ulocimp_minimizeSubtags(localeID, sink, favorScript, status);
},
status);
}
U_EXPORT void
ulocimp_minimizeSubtags(const char* localeID, ulocimp_minimizeSubtags(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
bool favorScript, bool favorScript,
UErrorCode* status) { UErrorCode& status) {
icu::CharString localeBuffer; if (U_FAILURE(status)) { return; }
{ icu::CharString localeBuffer = ulocimp_canonicalize(localeID, status);
icu::CharStringByteSink localeSink(&localeBuffer);
ulocimp_canonicalize(localeID, localeSink, status);
}
_uloc_minimizeSubtags(localeBuffer.data(), sink, favorScript, status); _uloc_minimizeSubtags(localeBuffer.data(), sink, favorScript, status);
} }
@ -728,22 +346,16 @@ static const char LANG_DIR_STRING[] =
U_CAPI UBool U_EXPORT2 U_CAPI UBool U_EXPORT2
uloc_isRightToLeft(const char *locale) { uloc_isRightToLeft(const char *locale) {
UErrorCode errorCode = U_ZERO_ERROR; UErrorCode errorCode = U_ZERO_ERROR;
char script[8]; icu::CharString lang;
int32_t scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &errorCode); icu::CharString script;
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || ulocimp_getSubtags(locale, &lang, &script, nullptr, nullptr, nullptr, errorCode);
scriptLength == 0) { if (U_FAILURE(errorCode) || script.isEmpty()) {
// Fastpath: We know the likely scripts and their writing direction // Fastpath: We know the likely scripts and their writing direction
// for some common languages. // for some common languages.
errorCode = U_ZERO_ERROR; if (!lang.isEmpty()) {
char lang[8]; const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang.data());
int32_t langLength = uloc_getLanguage(locale, lang, UPRV_LENGTHOF(lang), &errorCode);
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
return false;
}
if (langLength > 0) {
const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang);
if (langPtr != nullptr) { if (langPtr != nullptr) {
switch (langPtr[langLength]) { switch (langPtr[lang.length()]) {
case '-': return false; case '-': return false;
case '+': return true; case '+': return true;
default: break; // partial match of a longer code default: break; // partial match of a longer code
@ -752,21 +364,16 @@ uloc_isRightToLeft(const char *locale) {
} }
// Otherwise, find the likely script. // Otherwise, find the likely script.
errorCode = U_ZERO_ERROR; errorCode = U_ZERO_ERROR;
icu::CharString likely; icu::CharString likely = ulocimp_addLikelySubtags(locale, errorCode);
{ if (U_FAILURE(errorCode)) {
icu::CharStringByteSink sink(&likely);
ulocimp_addLikelySubtags(locale, sink, &errorCode);
}
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
return false; return false;
} }
scriptLength = uloc_getScript(likely.data(), script, UPRV_LENGTHOF(script), &errorCode); ulocimp_getSubtags(likely.data(), nullptr, &script, nullptr, nullptr, nullptr, errorCode);
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || if (U_FAILURE(errorCode) || script.isEmpty()) {
scriptLength == 0) {
return false; return false;
} }
} }
UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script); UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script.data());
return uscript_isRightToLeft(scriptCode); return uscript_isRightToLeft(scriptCode);
} }
@ -779,65 +386,52 @@ Locale::isRightToLeft() const {
U_NAMESPACE_END U_NAMESPACE_END
// The following must at least allow for rg key value (6) plus terminator (1). namespace {
#define ULOC_RG_BUFLEN 8 icu::CharString
GetRegionFromKey(const char* localeID, const char* key, UErrorCode& status) {
icu::CharString result;
U_CAPI int32_t U_EXPORT2 // First check for keyword value
ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion, icu::CharString kw = ulocimp_getKeywordValue(localeID, key, status);
char *region, int32_t regionCapacity, UErrorCode* status) { int32_t len = kw.length();
if (U_FAILURE(*status)) { if (U_SUCCESS(status) && len >= 3 && len <= 7) {
return 0;
}
char rgBuf[ULOC_RG_BUFLEN];
UErrorCode rgStatus = U_ZERO_ERROR;
// First check for rg keyword value
icu::CharString rg;
{
icu::CharStringByteSink sink(&rg);
ulocimp_getKeywordValue(localeID, "rg", sink, &rgStatus);
}
int32_t rgLen = rg.length();
if (U_FAILURE(rgStatus) || rgLen < 3 || rgLen > 7) {
rgLen = 0;
} else {
// chop off the subdivision code (which will generally be "zzzz" anyway) // chop off the subdivision code (which will generally be "zzzz" anyway)
const char* const data = rg.data(); const char* const data = kw.data();
if (uprv_isASCIILetter(data[0])) { if (uprv_isASCIILetter(data[0])) {
rgLen = 2; result.append(uprv_toupper(data[0]), status);
rgBuf[0] = uprv_toupper(data[0]); result.append(uprv_toupper(data[1]), status);
rgBuf[1] = uprv_toupper(data[1]);
} else { } else {
// assume three-digit region code // assume three-digit region code
rgLen = 3; result.append(data, 3, status);
uprv_memcpy(rgBuf, data, rgLen);
} }
} }
return result;
if (rgLen == 0) {
// No valid rg keyword value, try for unicode_region_subtag
rgLen = uloc_getCountry(localeID, rgBuf, ULOC_RG_BUFLEN, status);
if (U_FAILURE(*status)) {
rgLen = 0;
} else if (rgLen == 0 && inferRegion) {
// no unicode_region_subtag but inferRegion true, try likely subtags
rgStatus = U_ZERO_ERROR;
icu::CharString locBuf;
{
icu::CharStringByteSink sink(&locBuf);
ulocimp_addLikelySubtags(localeID, sink, &rgStatus);
}
if (U_SUCCESS(rgStatus)) {
rgLen = uloc_getCountry(locBuf.data(), rgBuf, ULOC_RG_BUFLEN, status);
if (U_FAILURE(*status)) {
rgLen = 0;
}
}
}
}
rgBuf[rgLen] = 0;
uprv_strncpy(region, rgBuf, regionCapacity);
return u_terminateChars(region, regionCapacity, rgLen, status);
} }
} // namespace
U_EXPORT icu::CharString
ulocimp_getRegionForSupplementalData(const char *localeID, bool inferRegion,
UErrorCode& status) {
if (U_FAILURE(status)) {
return {};
}
icu::CharString rgBuf = GetRegionFromKey(localeID, "rg", status);
if (U_SUCCESS(status) && rgBuf.isEmpty()) {
// No valid rg keyword value, try for unicode_region_subtag
rgBuf = ulocimp_getRegion(localeID, status);
if (U_SUCCESS(status) && rgBuf.isEmpty() && inferRegion) {
// Second check for sd keyword value
rgBuf = GetRegionFromKey(localeID, "sd", status);
if (U_SUCCESS(status) && rgBuf.isEmpty()) {
// no unicode_region_subtag but inferRegion true, try likely subtags
UErrorCode rgStatus = U_ZERO_ERROR;
icu::CharString locBuf = ulocimp_addLikelySubtags(localeID, rgStatus);
if (U_SUCCESS(rgStatus)) {
rgBuf = ulocimp_getRegion(locBuf.data(), status);
}
}
}
}
return rgBuf;
}

View File

@ -51,8 +51,7 @@ LocaleDistanceData::~LocaleDistanceData() {
delete[] paradigms; delete[] paradigms;
} }
// TODO(ICU-20777): Rename to just LikelySubtagsData. struct LikelySubtagsData {
struct XLikelySubtagsData {
UResourceBundle *langInfoBundle = nullptr; UResourceBundle *langInfoBundle = nullptr;
UniqueCharStrings strings; UniqueCharStrings strings;
CharStringMap languageAliases; CharStringMap languageAliases;
@ -63,14 +62,15 @@ struct XLikelySubtagsData {
LocaleDistanceData distanceData; LocaleDistanceData distanceData;
XLikelySubtagsData(UErrorCode &errorCode) : strings(errorCode) {} LikelySubtagsData(UErrorCode &errorCode) : strings(errorCode) {}
~XLikelySubtagsData() { ~LikelySubtagsData() {
ures_close(langInfoBundle); ures_close(langInfoBundle);
delete[] lsrs; delete[] lsrs;
} }
void load(UErrorCode &errorCode) { void load(UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return; }
langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode); langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode);
if (U_FAILURE(errorCode)) { return; } if (U_FAILURE(errorCode)) { return; }
StackUResourceBundle stackTempBundle; StackUResourceBundle stackTempBundle;
@ -231,6 +231,7 @@ struct XLikelySubtagsData {
private: private:
bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value, bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value,
LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) { LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return false; }
if (table.findValue(key, value)) { if (table.findValue(key, value)) {
ResourceArray stringArray = value.getArray(errorCode); ResourceArray stringArray = value.getArray(errorCode);
if (U_FAILURE(errorCode)) { return false; } if (U_FAILURE(errorCode)) { return false; }
@ -297,7 +298,7 @@ private:
} }
UnicodeString toRegion(const ResourceArray& m49Array, ResourceValue &value, int encoded, UErrorCode &errorCode) { UnicodeString toRegion(const ResourceArray& m49Array, ResourceValue &value, int encoded, UErrorCode &errorCode) {
if (encoded == 0 || encoded == 1) { if (U_FAILURE(errorCode) || encoded == 0 || encoded == 1) {
return UNICODE_STRING_SIMPLE(""); return UNICODE_STRING_SIMPLE("");
} }
encoded &= 0x00ffffff; encoded &= 0x00ffffff;
@ -315,6 +316,7 @@ private:
bool readLSREncodedStrings(const ResourceTable &table, const char* key, ResourceValue &value, const ResourceArray& m49Array, bool readLSREncodedStrings(const ResourceTable &table, const char* key, ResourceValue &value, const ResourceArray& m49Array,
LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) { LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return false; }
if (table.findValue(key, value)) { if (table.findValue(key, value)) {
const int32_t* vectors = value.getIntVector(length, errorCode); const int32_t* vectors = value.getIntVector(length, errorCode);
if (U_FAILURE(errorCode)) { return false; } if (U_FAILURE(errorCode)) { return false; }
@ -339,7 +341,7 @@ private:
namespace { namespace {
XLikelySubtags *gLikelySubtags = nullptr; LikelySubtags *gLikelySubtags = nullptr;
UVector *gMacroregions = nullptr; UVector *gMacroregions = nullptr;
UInitOnce gInitOnce {}; UInitOnce gInitOnce {};
@ -352,21 +354,36 @@ UBool U_CALLCONV cleanup() {
return true; return true;
} }
static const char16_t RANGE_MARKER = 0x7E; /* '~' */ constexpr const char16_t* MACROREGION_HARDCODE[] = {
UVector* loadMacroregions(UErrorCode &status) { u"001~3",
LocalPointer<UVector> newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); u"005",
u"009",
u"011",
u"013~5",
u"017~9",
u"021",
u"029",
u"030",
u"034~5",
u"039",
u"053~4",
u"057",
u"061",
u"142~3",
u"145",
u"150~1",
u"154~5",
u"202",
u"419",
u"EU",
u"EZ",
u"QO",
u"UN",
};
LocalUResourceBundlePointer supplementalData(ures_openDirect(nullptr,"supplementalData",&status)); constexpr char16_t RANGE_MARKER = 0x7E; /* '~' */
LocalUResourceBundlePointer idValidity(ures_getByKey(supplementalData.getAlias(),"idValidity",nullptr,&status)); void processMacroregionRange(const UnicodeString& regionName, UVector* newMacroRegions, UErrorCode& status) {
LocalUResourceBundlePointer regionList(ures_getByKey(idValidity.getAlias(),"region",nullptr,&status)); if (U_FAILURE(status)) { return; }
LocalUResourceBundlePointer regionMacro(ures_getByKey(regionList.getAlias(),"macroregion",nullptr,&status));
if (U_FAILURE(status)) {
return nullptr;
}
while (U_SUCCESS(status) && ures_hasNext(regionMacro.getAlias())) {
UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),nullptr,&status);
int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER);
char16_t buf[6]; char16_t buf[6];
regionName.extract(buf,6,status); regionName.extract(buf,6,status);
@ -382,20 +399,68 @@ UVector* loadMacroregions(UErrorCode &status) {
LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status);
newMacroRegions->adoptElement(newRegion.orphan(),status); newMacroRegions->adoptElement(newRegion.orphan(),status);
} }
}
#if U_DEBUG
UVector* loadMacroregions(UErrorCode &status) {
if (U_FAILURE(status)) { return nullptr; }
LocalPointer<UVector> newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status);
LocalUResourceBundlePointer supplementalData(ures_openDirect(nullptr,"supplementalData",&status));
LocalUResourceBundlePointer idValidity(ures_getByKey(supplementalData.getAlias(),"idValidity",nullptr,&status));
LocalUResourceBundlePointer regionList(ures_getByKey(idValidity.getAlias(),"region",nullptr,&status));
LocalUResourceBundlePointer regionMacro(ures_getByKey(regionList.getAlias(),"macroregion",nullptr,&status));
if (U_FAILURE(status)) {
return nullptr;
} }
while (ures_hasNext(regionMacro.getAlias())) {
UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),nullptr,&status);
processMacroregionRange(regionName, newMacroRegions.getAlias(), status);
if (U_FAILURE(status)) {
return nullptr;
}
}
return newMacroRegions.orphan();
}
#endif // U_DEBUG
UVector* getStaticMacroregions(UErrorCode &status) {
if (U_FAILURE(status)) { return nullptr; }
LocalPointer<UVector> newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status);
if (U_FAILURE(status)) {
return nullptr;
}
for (const auto *region : MACROREGION_HARDCODE) {
UnicodeString regionName(region);
processMacroregionRange(regionName, newMacroRegions.getAlias(), status);
if (U_FAILURE(status)) {
return nullptr;
}
}
return newMacroRegions.orphan(); return newMacroRegions.orphan();
} }
} // namespace } // namespace
void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) { void U_CALLCONV LikelySubtags::initLikelySubtags(UErrorCode &errorCode) {
// This function is invoked only via umtx_initOnce(). // This function is invoked only via umtx_initOnce().
U_ASSERT(gLikelySubtags == nullptr); U_ASSERT(gLikelySubtags == nullptr);
XLikelySubtagsData data(errorCode); LikelySubtagsData data(errorCode);
data.load(errorCode); data.load(errorCode);
if (U_FAILURE(errorCode)) { return; } if (U_FAILURE(errorCode)) { return; }
gLikelySubtags = new XLikelySubtags(data); gLikelySubtags = new LikelySubtags(data);
gMacroregions = loadMacroregions(errorCode); gMacroregions = getStaticMacroregions(errorCode);
#if U_DEBUG
auto macroregionsFromData = loadMacroregions(errorCode);
U_ASSERT((*gMacroregions) == (*macroregionsFromData));
delete macroregionsFromData;
#endif
if (U_FAILURE(errorCode) || gLikelySubtags == nullptr || gMacroregions == nullptr) { if (U_FAILURE(errorCode) || gLikelySubtags == nullptr || gMacroregions == nullptr) {
delete gLikelySubtags; delete gLikelySubtags;
delete gMacroregions; delete gMacroregions;
@ -406,13 +471,13 @@ void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) {
ucln_common_registerCleanup(UCLN_COMMON_LIKELY_SUBTAGS, cleanup); ucln_common_registerCleanup(UCLN_COMMON_LIKELY_SUBTAGS, cleanup);
} }
const XLikelySubtags *XLikelySubtags::getSingleton(UErrorCode &errorCode) { const LikelySubtags *LikelySubtags::getSingleton(UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return nullptr; } if (U_FAILURE(errorCode)) { return nullptr; }
umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode); umtx_initOnce(gInitOnce, &LikelySubtags::initLikelySubtags, errorCode);
return gLikelySubtags; return gLikelySubtags;
} }
XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) : LikelySubtags::LikelySubtags(LikelySubtagsData &data) :
langInfoBundle(data.langInfoBundle), langInfoBundle(data.langInfoBundle),
strings(data.strings.orphanCharStrings()), strings(data.strings.orphanCharStrings()),
languageAliases(std::move(data.languageAliases)), languageAliases(std::move(data.languageAliases)),
@ -421,7 +486,7 @@ XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) :
lsrs(data.lsrs), lsrs(data.lsrs),
#if U_DEBUG #if U_DEBUG
lsrsLength(data.lsrsLength), lsrsLength(data.lsrsLength),
#endif #endif // U_DEBUG
distanceData(std::move(data.distanceData)) { distanceData(std::move(data.distanceData)) {
data.langInfoBundle = nullptr; data.langInfoBundle = nullptr;
data.lsrs = nullptr; data.lsrs = nullptr;
@ -447,18 +512,19 @@ XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) :
} }
} }
XLikelySubtags::~XLikelySubtags() { LikelySubtags::~LikelySubtags() {
ures_close(langInfoBundle); ures_close(langInfoBundle);
delete strings; delete strings;
delete[] lsrs; delete[] lsrs;
} }
LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, LSR LikelySubtags::makeMaximizedLsrFrom(const Locale &locale,
bool returnInputIfUnmatch, bool returnInputIfUnmatch,
UErrorCode &errorCode) const { UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
if (locale.isBogus()) { if (locale.isBogus()) {
errorCode = U_ILLEGAL_ARGUMENT_ERROR; errorCode = U_ILLEGAL_ARGUMENT_ERROR;
return LSR("", "", "", LSR::EXPLICIT_LSR); return {};
} }
const char *name = locale.getName(); const char *name = locale.getName();
if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=") if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=")
@ -490,10 +556,11 @@ const char *getCanonical(const CharStringMap &aliases, const char *alias) {
} // namespace } // namespace
LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, const char *region, LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, const char *region,
const char *variant, const char *variant,
bool returnInputIfUnmatch, bool returnInputIfUnmatch,
UErrorCode &errorCode) const { UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
// Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK.
// They should match only themselves, // They should match only themselves,
// not other locales with what looks like the same language and script subtags. // not other locales with what looks like the same language and script subtags.
@ -501,12 +568,21 @@ LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, c
if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) { if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) {
switch (c1) { switch (c1) {
case 'A': case 'A':
if (returnInputIfUnmatch) {
return LSR(language, script, region, LSR::EXPLICIT_LSR);
}
return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region,
LSR::EXPLICIT_LSR, errorCode); LSR::EXPLICIT_LSR, errorCode);
case 'B': case 'B':
if (returnInputIfUnmatch) {
return LSR(language, script, region, LSR::EXPLICIT_LSR);
}
return LSR(PSEUDO_BIDI_PREFIX, language, script, region, return LSR(PSEUDO_BIDI_PREFIX, language, script, region,
LSR::EXPLICIT_LSR, errorCode); LSR::EXPLICIT_LSR, errorCode);
case 'C': case 'C':
if (returnInputIfUnmatch) {
return LSR(language, script, region, LSR::EXPLICIT_LSR);
}
return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, return LSR(PSEUDO_CRACKED_PREFIX, language, script, region,
LSR::EXPLICIT_LSR, errorCode); LSR::EXPLICIT_LSR, errorCode);
default: // normal locale default: // normal locale
@ -536,9 +612,10 @@ LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, c
return maximize(language, script, region, returnInputIfUnmatch, errorCode); return maximize(language, script, region, returnInputIfUnmatch, errorCode);
} }
LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region, LSR LikelySubtags::maximize(const char *language, const char *script, const char *region,
bool returnInputIfUnmatch, bool returnInputIfUnmatch,
UErrorCode &errorCode) const { UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
return maximize({language, (int32_t)uprv_strlen(language)}, return maximize({language, (int32_t)uprv_strlen(language)},
{script, (int32_t)uprv_strlen(script)}, {script, (int32_t)uprv_strlen(script)},
{region, (int32_t)uprv_strlen(region)}, {region, (int32_t)uprv_strlen(region)},
@ -546,23 +623,21 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha
errorCode); errorCode);
} }
bool XLikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) const { bool LikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) const {
if (U_FAILURE(errorCode)) { return false; }
// In Java, we use Region class. In C++, since Region is under i18n, // In Java, we use Region class. In C++, since Region is under i18n,
// we read the same data used by Region into gMacroregions avoid dependency // we read the same data used by Region into gMacroregions avoid dependency
// from common to i18n/region.cpp // from common to i18n/region.cpp
if (U_FAILURE(errorCode)) { return false; } umtx_initOnce(gInitOnce, &LikelySubtags::initLikelySubtags, errorCode);
umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode);
if (U_FAILURE(errorCode)) { return false; } if (U_FAILURE(errorCode)) { return false; }
UnicodeString str(UnicodeString::fromUTF8(region)); UnicodeString str(UnicodeString::fromUTF8(region));
return gMacroregions->contains((void *)&str); return gMacroregions->contains((void *)&str);
} }
LSR XLikelySubtags::maximize(StringPiece language, StringPiece script, StringPiece region, LSR LikelySubtags::maximize(StringPiece language, StringPiece script, StringPiece region,
bool returnInputIfUnmatch, bool returnInputIfUnmatch,
UErrorCode &errorCode) const { UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) { return {}; }
return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode);
}
if (language.compare("und") == 0) { if (language.compare("und") == 0) {
language = ""; language = "";
} }
@ -681,7 +756,7 @@ LSR XLikelySubtags::maximize(StringPiece language, StringPiece script, StringPie
return LSR(language, script, region, retainMask, errorCode); return LSR(language, script, region, retainMask, errorCode);
} }
int32_t XLikelySubtags::compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const { int32_t LikelySubtags::compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const {
// If likelyInfo >= 0: // If likelyInfo >= 0:
// likelyInfo bit 1 is set if the previous comparison with lsr // likelyInfo bit 1 is set if the previous comparison with lsr
// was for equal language and script. // was for equal language and script.
@ -723,7 +798,7 @@ int32_t XLikelySubtags::compareLikely(const LSR &lsr, const LSR &other, int32_t
} }
// Subset of maximize(). // Subset of maximize().
int32_t XLikelySubtags::getLikelyIndex(const char *language, const char *script) const { int32_t LikelySubtags::getLikelyIndex(const char *language, const char *script) const {
if (uprv_strcmp(language, "und") == 0) { if (uprv_strcmp(language, "und") == 0) {
language = ""; language = "";
} }
@ -781,7 +856,7 @@ int32_t XLikelySubtags::getLikelyIndex(const char *language, const char *script)
return value; return value;
} }
int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) { int32_t LikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) {
UStringTrieResult result; UStringTrieResult result;
uint8_t c; uint8_t c;
if ((c = s[i]) == 0) { if ((c = s[i]) == 0) {
@ -814,7 +889,7 @@ int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) {
default: return -1; default: return -1;
} }
} }
int32_t XLikelySubtags::trieNext(BytesTrie &iter, StringPiece s, int32_t i) { int32_t LikelySubtags::trieNext(BytesTrie &iter, StringPiece s, int32_t i) {
UStringTrieResult result; UStringTrieResult result;
uint8_t c; uint8_t c;
if (s.length() == i) { if (s.length() == i) {
@ -848,14 +923,13 @@ int32_t XLikelySubtags::trieNext(BytesTrie &iter, StringPiece s, int32_t i) {
} }
} }
LSR XLikelySubtags::minimizeSubtags(StringPiece language, StringPiece script, LSR LikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
StringPiece region, StringPiece region,
bool favorScript, bool favorScript,
UErrorCode &errorCode) const { UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
LSR max = maximize(language, script, region, true, errorCode); LSR max = maximize(language, script, region, true, errorCode);
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) { return {}; }
return max;
}
// If no match, return it. // If no match, return it.
if (uprv_strlen(max.language) == 0 && if (uprv_strlen(max.language) == 0 &&
uprv_strlen(max.script) == 0 && uprv_strlen(max.script) == 0 &&
@ -868,9 +942,7 @@ LSR XLikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
} }
// try language // try language
LSR test = maximize(max.language, "", "", true, errorCode); LSR test = maximize(max.language, "", "", true, errorCode);
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) { return {}; }
return max;
}
if (test.isEquivalentTo(max)) { if (test.isEquivalentTo(max)) {
return LSR(max.language, "", "", LSR::DONT_CARE_FLAGS, errorCode); return LSR(max.language, "", "", LSR::DONT_CARE_FLAGS, errorCode);
} }
@ -879,27 +951,21 @@ LSR XLikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
// favor Region // favor Region
// try language and region // try language and region
test = maximize(max.language, "", max.region, true, errorCode); test = maximize(max.language, "", max.region, true, errorCode);
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) { return {}; }
return max;
}
if (test.isEquivalentTo(max)) { if (test.isEquivalentTo(max)) {
return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode);
} }
} }
// try language and script // try language and script
test = maximize(max.language, max.script, "", true, errorCode); test = maximize(max.language, max.script, "", true, errorCode);
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) { return {}; }
return max;
}
if (test.isEquivalentTo(max)) { if (test.isEquivalentTo(max)) {
return LSR(max.language, max.script, "", LSR::DONT_CARE_FLAGS, errorCode); return LSR(max.language, max.script, "", LSR::DONT_CARE_FLAGS, errorCode);
} }
if (favorScript) { if (favorScript) {
// try language and region // try language and region
test = maximize(max.language, "", max.region, true, errorCode); test = maximize(max.language, "", max.region, true, errorCode);
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) { return {}; }
return max;
}
if (test.isEquivalentTo(max)) { if (test.isEquivalentTo(max)) {
return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode);
} }

View File

@ -19,7 +19,7 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
struct XLikelySubtagsData; struct LikelySubtagsData;
struct LocaleDistanceData { struct LocaleDistanceData {
LocaleDistanceData() = default; LocaleDistanceData() = default;
@ -37,15 +37,14 @@ private:
LocaleDistanceData &operator=(const LocaleDistanceData &) = delete; LocaleDistanceData &operator=(const LocaleDistanceData &) = delete;
}; };
// TODO(ICU-20777): Rename to just LikelySubtags. class LikelySubtags final : public UMemory {
class XLikelySubtags final : public UMemory {
public: public:
~XLikelySubtags(); ~LikelySubtags();
static constexpr int32_t SKIP_SCRIPT = 1; static constexpr int32_t SKIP_SCRIPT = 1;
// VisibleForTesting // VisibleForTesting
static const XLikelySubtags *getSingleton(UErrorCode &errorCode); static const LikelySubtags *getSingleton(UErrorCode &errorCode);
// VisibleForTesting // VisibleForTesting
LSR makeMaximizedLsrFrom(const Locale &locale, LSR makeMaximizedLsrFrom(const Locale &locale,
@ -72,9 +71,9 @@ public:
const LocaleDistanceData &getDistanceData() const { return distanceData; } const LocaleDistanceData &getDistanceData() const { return distanceData; }
private: private:
XLikelySubtags(XLikelySubtagsData &data); LikelySubtags(LikelySubtagsData &data);
XLikelySubtags(const XLikelySubtags &other) = delete; LikelySubtags(const LikelySubtags &other) = delete;
XLikelySubtags &operator=(const XLikelySubtags &other) = delete; LikelySubtags &operator=(const LikelySubtags &other) = delete;
static void initLikelySubtags(UErrorCode &errorCode); static void initLikelySubtags(UErrorCode &errorCode);
@ -120,7 +119,7 @@ private:
int32_t lsrsLength; int32_t lsrsLength;
#endif #endif
// distance/matcher data: see comment in XLikelySubtagsData::load() // distance/matcher data: see comment in LikelySubtagsData::load()
LocaleDistanceData distanceData; LocaleDistanceData distanceData;
}; };

View File

@ -28,7 +28,6 @@
*/ */
#include "locmap.h" #include "locmap.h"
#include "bytesinkutil.h"
#include "charstr.h" #include "charstr.h"
#include "cstring.h" #include "cstring.h"
#include "cmemory.h" #include "cmemory.h"
@ -49,6 +48,8 @@
* [MS-LCID] Windows Language Code Identifier (LCID) Reference * [MS-LCID] Windows Language Code Identifier (LCID) Reference
*/ */
namespace {
/* /*
//////////////////////////////////////////////// ////////////////////////////////////////////////
// //
@ -87,7 +88,7 @@ typedef struct ILcidPosixMap
* @param posixID posix ID of the language_TERRITORY such as 'de_CH' * @param posixID posix ID of the language_TERRITORY such as 'de_CH'
*/ */
#define ILCID_POSIX_ELEMENT_ARRAY(hostID, languageID, posixID) \ #define ILCID_POSIX_ELEMENT_ARRAY(hostID, languageID, posixID) \
static const ILcidPosixElement locmap_ ## languageID [] = { \ constexpr ILcidPosixElement locmap_ ## languageID [] = { \
{LANGUAGE_LCID(hostID), #languageID}, /* parent locale */ \ {LANGUAGE_LCID(hostID), #languageID}, /* parent locale */ \
{hostID, #posixID}, \ {hostID, #posixID}, \
}; };
@ -97,7 +98,7 @@ static const ILcidPosixElement locmap_ ## languageID [] = { \
* @param id the POSIX ID, either a language or language_TERRITORY * @param id the POSIX ID, either a language or language_TERRITORY
*/ */
#define ILCID_POSIX_SUBTABLE(id) \ #define ILCID_POSIX_SUBTABLE(id) \
static const ILcidPosixElement locmap_ ## id [] = constexpr ILcidPosixElement locmap_ ## id [] =
/** /**
@ -796,7 +797,7 @@ ILCID_POSIX_SUBTABLE(zh) {
ILCID_POSIX_ELEMENT_ARRAY(0x0435, zu, zu_ZA) ILCID_POSIX_ELEMENT_ARRAY(0x0435, zu, zu_ZA)
/* This must be static and grouped by LCID. */ /* This must be static and grouped by LCID. */
static const ILcidPosixMap gPosixIDmap[] = { constexpr ILcidPosixMap gPosixIDmap[] = {
ILCID_POSIX_MAP(af), /* af Afrikaans 0x36 */ ILCID_POSIX_MAP(af), /* af Afrikaans 0x36 */
ILCID_POSIX_MAP(am), /* am Amharic 0x5e */ ILCID_POSIX_MAP(am), /* am Amharic 0x5e */
ILCID_POSIX_MAP(ar), /* ar Arabic 0x01 */ ILCID_POSIX_MAP(ar), /* ar Arabic 0x01 */
@ -945,14 +946,14 @@ static const ILcidPosixMap gPosixIDmap[] = {
ILCID_POSIX_MAP(zu), /* zu Zulu 0x35 */ ILCID_POSIX_MAP(zu), /* zu Zulu 0x35 */
}; };
static const uint32_t gLocaleCount = UPRV_LENGTHOF(gPosixIDmap); constexpr uint32_t gLocaleCount = UPRV_LENGTHOF(gPosixIDmap);
/** /**
* Do not call this function. It is called by hostID. * Do not call this function. It is called by hostID.
* The function is not private because this struct must stay as a C struct, * The function is not private because this struct must stay as a C struct,
* and this is an internal class. * and this is an internal class.
*/ */
static int32_t int32_t
idCmp(const char* id1, const char* id2) idCmp(const char* id1, const char* id2)
{ {
int32_t diffIdx = 0; int32_t diffIdx = 0;
@ -972,9 +973,10 @@ idCmp(const char* id1, const char* id2)
* no equivalent Windows LCID. * no equivalent Windows LCID.
* @return the LCID * @return the LCID
*/ */
static uint32_t uint32_t
getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode* status) getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status)
{ {
if (U_FAILURE(status)) { return locmap_root->hostID; }
int32_t bestIdx = 0; int32_t bestIdx = 0;
int32_t bestIdxDiff = 0; int32_t bestIdxDiff = 0;
int32_t posixIDlen = (int32_t)uprv_strlen(posixID); int32_t posixIDlen = (int32_t)uprv_strlen(posixID);
@ -996,16 +998,16 @@ getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode* status)
if ((posixID[bestIdxDiff] == '_' || posixID[bestIdxDiff] == '@') if ((posixID[bestIdxDiff] == '_' || posixID[bestIdxDiff] == '@')
&& this_0->regionMaps[bestIdx].posixID[bestIdxDiff] == 0) && this_0->regionMaps[bestIdx].posixID[bestIdxDiff] == 0)
{ {
*status = U_USING_FALLBACK_WARNING; status = U_USING_FALLBACK_WARNING;
return this_0->regionMaps[bestIdx].hostID; return this_0->regionMaps[bestIdx].hostID;
} }
/*no match found */ /*no match found */
*status = U_ILLEGAL_ARGUMENT_ERROR; status = U_ILLEGAL_ARGUMENT_ERROR;
return this_0->regionMaps->hostID; return locmap_root->hostID;
} }
static const char* const char*
getPosixID(const ILcidPosixMap *this_0, uint32_t hostID) getPosixID(const ILcidPosixMap *this_0, uint32_t hostID)
{ {
uint32_t i; uint32_t i;
@ -1035,19 +1037,21 @@ getPosixID(const ILcidPosixMap *this_0, uint32_t hostID)
* quz -> qu * quz -> qu
* prs -> fa * prs -> fa
*/ */
#define FIX_LANGUAGE_ID_TAG(buffer, len) \ void FIX_LANGUAGE_ID_TAG(char* buffer, int32_t len) {
if (len >= 3) { \ if (len >= 3) {
if (buffer[0] == 'q' && buffer[1] == 'u' && buffer[2] == 'z') {\ if (buffer[0] == 'q' && buffer[1] == 'u' && buffer[2] == 'z') {
buffer[2] = 0; \ buffer[2] = 0;
uprv_strcat(buffer, buffer+3); \ uprv_strcat(buffer, buffer+3);
} else if (buffer[0] == 'p' && buffer[1] == 'r' && buffer[2] == 's') {\ } else if (buffer[0] == 'p' && buffer[1] == 'r' && buffer[2] == 's') {
buffer[0] = 'f'; buffer[1] = 'a'; buffer[2] = 0; \ buffer[0] = 'f'; buffer[1] = 'a'; buffer[2] = 0;
uprv_strcat(buffer, buffer+3); \ uprv_strcat(buffer, buffer+3);
} \
} }
}
}
#endif #endif
} // namespace
U_CAPI int32_t U_CAPI int32_t
uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UErrorCode* status) uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UErrorCode* status)
{ {
@ -1147,7 +1151,7 @@ uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UEr
/* no match found */ /* no match found */
*status = U_ILLEGAL_ARGUMENT_ERROR; *status = U_ILLEGAL_ARGUMENT_ERROR;
return -1; return 0;
} }
/* /*
@ -1176,11 +1180,7 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status)
// Check any for keywords. // Check any for keywords.
if (uprv_strchr(localeID, '@')) if (uprv_strchr(localeID, '@'))
{ {
icu::CharString collVal; icu::CharString collVal = ulocimp_getKeywordValue(localeID, "collation", *status);
{
icu::CharStringByteSink sink(&collVal);
ulocimp_getKeywordValue(localeID, "collation", sink, status);
}
if (U_SUCCESS(*status) && !collVal.isEmpty()) if (U_SUCCESS(*status) && !collVal.isEmpty())
{ {
// If it contains the keyword collation, return 0 so that the LCID lookup table will be used. // If it contains the keyword collation, return 0 so that the LCID lookup table will be used.
@ -1189,10 +1189,7 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status)
else else
{ {
// If the locale ID contains keywords other than collation, just use the base name. // If the locale ID contains keywords other than collation, just use the base name.
{ baseName = ulocimp_getBaseName(localeID, *status);
icu::CharStringByteSink sink(&baseName);
ulocimp_getBaseName(localeID, sink, status);
}
if (U_SUCCESS(*status) && !baseName.isEmpty()) if (U_SUCCESS(*status) && !baseName.isEmpty())
{ {
mylocaleID = baseName.data(); mylocaleID = baseName.data();
@ -1201,11 +1198,7 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status)
} }
// this will change it from de_DE@collation=phonebook to de-DE-u-co-phonebk form // this will change it from de_DE@collation=phonebook to de-DE-u-co-phonebk form
icu::CharString asciiBCP47Tag; icu::CharString asciiBCP47Tag = ulocimp_toLanguageTag(mylocaleID, false, *status);
{
icu::CharStringByteSink sink(&asciiBCP47Tag);
ulocimp_toLanguageTag(mylocaleID, sink, false, status);
}
if (U_SUCCESS(*status)) if (U_SUCCESS(*status))
{ {
@ -1253,6 +1246,14 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status)
U_CAPI uint32_t U_CAPI uint32_t
uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status) uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
{ {
if (U_FAILURE(*status) ||
langID == nullptr ||
posixID == nullptr ||
uprv_strlen(langID) < 2 ||
uprv_strlen(posixID) < 2) {
return locmap_root->hostID;
}
// This function does the table lookup when native platform name->lcid conversion isn't available, // This function does the table lookup when native platform name->lcid conversion isn't available,
// or for locales that don't follow patterns the platform expects. // or for locales that don't follow patterns the platform expects.
uint32_t low = 0; uint32_t low = 0;
@ -1266,11 +1267,6 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
UErrorCode myStatus; UErrorCode myStatus;
uint32_t idx; uint32_t idx;
/* Check for incomplete id. */
if (!langID || !posixID || uprv_strlen(langID) < 2 || uprv_strlen(posixID) < 2) {
return 0;
}
/*Binary search for the map entry for normal cases */ /*Binary search for the map entry for normal cases */
while (high > low) /*binary search*/{ while (high > low) /*binary search*/{
@ -1288,7 +1284,7 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
low = mid; low = mid;
} }
else /*we found it*/{ else /*we found it*/{
return getHostID(&gPosixIDmap[mid], posixID, status); return getHostID(&gPosixIDmap[mid], posixID, *status);
} }
oldmid = mid; oldmid = mid;
} }
@ -1299,7 +1295,7 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
*/ */
for (idx = 0; idx < gLocaleCount; idx++ ) { for (idx = 0; idx < gLocaleCount; idx++ ) {
myStatus = U_ZERO_ERROR; myStatus = U_ZERO_ERROR;
value = getHostID(&gPosixIDmap[idx], posixID, &myStatus); value = getHostID(&gPosixIDmap[idx], posixID, myStatus);
if (myStatus == U_ZERO_ERROR) { if (myStatus == U_ZERO_ERROR) {
return value; return value;
} }
@ -1315,5 +1311,5 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
/* no match found */ /* no match found */
*status = U_ILLEGAL_ARGUMENT_ERROR; *status = U_ILLEGAL_ARGUMENT_ERROR;
return 0; /* return international (root) */ return locmap_root->hostID; /* return international (root) */
} }

View File

@ -24,7 +24,6 @@
#include "unicode/putil.h" #include "unicode/putil.h"
#include "unicode/uloc.h" #include "unicode/uloc.h"
#include "unicode/ures.h" #include "unicode/ures.h"
#include "bytesinkutil.h"
#include "charstr.h" #include "charstr.h"
#include "cstring.h" #include "cstring.h"
#include "ulocimp.h" #include "ulocimp.h"
@ -50,10 +49,10 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
int32_t *pLength, int32_t *pLength,
UErrorCode *pErrorCode) UErrorCode *pErrorCode)
{ {
if (U_FAILURE(*pErrorCode)) { return nullptr; }
/* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/ /* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/
const char16_t *item=nullptr; const char16_t *item=nullptr;
UErrorCode errorCode; UErrorCode errorCode;
char explicitFallbackName[ULOC_FULLNAME_CAPACITY] = {0};
/* /*
* open the bundle for the current locale * open the bundle for the current locale
@ -129,14 +128,15 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
break; break;
} }
u_UCharsToChars(fallbackLocale, explicitFallbackName, len); icu::CharString explicitFallbackName;
explicitFallbackName.appendInvariantChars(fallbackLocale, len, errorCode);
/* guard against recursive fallback */ /* guard against recursive fallback */
if(uprv_strcmp(explicitFallbackName, locale)==0){ if (explicitFallbackName == locale) {
*pErrorCode = U_INTERNAL_PROGRAM_ERROR; *pErrorCode = U_INTERNAL_PROGRAM_ERROR;
break; break;
} }
rb.adoptInstead(ures_open(path, explicitFallbackName, &errorCode)); rb.adoptInstead(ures_open(path, explicitFallbackName.data(), &errorCode));
if(U_FAILURE(errorCode)){ if(U_FAILURE(errorCode)){
*pErrorCode = errorCode; *pErrorCode = errorCode;
break; break;
@ -150,21 +150,21 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
return item; return item;
} }
static ULayoutType namespace {
ULayoutType
_uloc_getOrientationHelper(const char* localeId, _uloc_getOrientationHelper(const char* localeId,
const char* key, const char* key,
UErrorCode *status) UErrorCode& status)
{ {
ULayoutType result = ULOC_LAYOUT_UNKNOWN; ULayoutType result = ULOC_LAYOUT_UNKNOWN;
if (!U_FAILURE(*status)) { if (U_FAILURE(status)) { return result; }
icu::CharString localeBuffer;
{ icu::CharString localeBuffer = ulocimp_canonicalize(localeId, status);
icu::CharStringByteSink sink(&localeBuffer);
ulocimp_canonicalize(localeId, sink, status); if (U_FAILURE(status)) { return result; }
}
if (!U_FAILURE(*status)) {
int32_t length = 0; int32_t length = 0;
const char16_t* const value = const char16_t* const value =
uloc_getTableStringWithFallback( uloc_getTableStringWithFallback(
@ -174,9 +174,11 @@ _uloc_getOrientationHelper(const char* localeId,
nullptr, nullptr,
key, key,
&length, &length,
status); &status);
if (!U_FAILURE(*status) && length != 0) { if (U_FAILURE(status)) { return result; }
if (length != 0) {
switch(value[0]) switch(value[0])
{ {
case 0x0062: /* 'b' */ case 0x0062: /* 'b' */
@ -192,21 +194,21 @@ _uloc_getOrientationHelper(const char* localeId,
result = ULOC_LAYOUT_TTB; result = ULOC_LAYOUT_TTB;
break; break;
default: default:
*status = U_INTERNAL_PROGRAM_ERROR; status = U_INTERNAL_PROGRAM_ERROR;
break; break;
} }
} }
}
}
return result; return result;
} }
} // namespace
U_CAPI ULayoutType U_EXPORT2 U_CAPI ULayoutType U_EXPORT2
uloc_getCharacterOrientation(const char* localeId, uloc_getCharacterOrientation(const char* localeId,
UErrorCode *status) UErrorCode *status)
{ {
return _uloc_getOrientationHelper(localeId, "characters", status); return _uloc_getOrientationHelper(localeId, "characters", *status);
} }
/** /**
@ -220,5 +222,5 @@ U_CAPI ULayoutType U_EXPORT2
uloc_getLineOrientation(const char* localeId, uloc_getLineOrientation(const char* localeId,
UErrorCode *status) UErrorCode *status)
{ {
return _uloc_getOrientationHelper(localeId, "lines", status); return _uloc_getOrientationHelper(localeId, "lines", *status);
} }

View File

@ -145,9 +145,7 @@ LocaleUtility::canonicalLocaleString(const UnicodeString* id, UnicodeString& res
Locale& Locale&
LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result) LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
{ {
enum { BUFLEN = 128 }; // larger than ever needed if (id.isBogus()) {
if (id.isBogus() || id.length() >= BUFLEN) {
result.setToBogus(); result.setToBogus();
} else { } else {
/* /*
@ -168,24 +166,29 @@ LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
* *
* There should be only at most one '@' in a locale ID. * There should be only at most one '@' in a locale ID.
*/ */
char buffer[BUFLEN]; CharString buffer;
int32_t prev, i; int32_t prev, i;
prev = 0; prev = 0;
for(;;) { UErrorCode status = U_ZERO_ERROR;
do {
i = id.indexOf((char16_t)0x40, prev); i = id.indexOf((char16_t)0x40, prev);
if(i < 0) { if(i < 0) {
// no @ between prev and the rest of the string // no @ between prev and the rest of the string
id.extract(prev, INT32_MAX, buffer + prev, BUFLEN - prev, US_INV); buffer.appendInvariantChars(id.tempSubString(prev), status);
break; // done break; // done
} else { } else {
// normal invariant-character conversion for text between @s // normal invariant-character conversion for text between @s
id.extract(prev, i - prev, buffer + prev, BUFLEN - prev, US_INV); buffer.appendInvariantChars(id.tempSubString(prev, i - prev), status);
// manually "convert" U+0040 at id[i] into '@' at buffer[i] // manually "convert" U+0040 at id[i] into '@' at buffer[i]
buffer[i] = '@'; buffer.append('@', status);
prev = i + 1; prev = i + 1;
} }
} while (U_SUCCESS(status));
if (U_FAILURE(status)) {
result.setToBogus();
} else {
result = Locale::createFromName(buffer.data());
} }
result = Locale::createFromName(buffer);
} }
return result; return result;
} }
@ -259,7 +262,7 @@ LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID)
return htp; return htp;
} }
UBool bool
LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& child) LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& child)
{ {
return child.indexOf(root) == 0 && return child.indexOf(root) == 0 &&
@ -271,5 +274,3 @@ U_NAMESPACE_END
/* !UCONFIG_NO_SERVICE */ /* !UCONFIG_NO_SERVICE */
#endif #endif

View File

@ -28,7 +28,7 @@ public:
static Locale& initLocaleFromName(const UnicodeString& id, Locale& result); static Locale& initLocaleFromName(const UnicodeString& id, Locale& result);
static UnicodeString& initNameFromLocale(const Locale& locale, UnicodeString& result); static UnicodeString& initNameFromLocale(const Locale& locale, UnicodeString& result);
static const Hashtable* getAvailableLocaleNames(const UnicodeString& bundleID); static const Hashtable* getAvailableLocaleNames(const UnicodeString& bundleID);
static UBool isFallbackOf(const UnicodeString& root, const UnicodeString& child); static bool isFallbackOf(const UnicodeString& root, const UnicodeString& child);
}; };
U_NAMESPACE_END U_NAMESPACE_END

View File

@ -999,7 +999,6 @@ MessagePattern::parseDouble(int32_t start, int32_t limit, UBool allowInfinity,
} }
setParseError(parseError, start /*, limit*/); // Bad syntax for numeric value. setParseError(parseError, start /*, limit*/); // Bad syntax for numeric value.
errorCode=U_PATTERN_SYNTAX_ERROR; errorCode=U_PATTERN_SYNTAX_ERROR;
return;
} }
int32_t int32_t

View File

@ -1390,8 +1390,11 @@ Normalizer2Impl::composePair(UChar32 a, UChar32 b) const {
} else if(norm16<minYesNoMappingsOnly) { } else if(norm16<minYesNoMappingsOnly) {
// a combines forward. // a combines forward.
if(isJamoL(norm16)) { if(isJamoL(norm16)) {
if (b < Hangul::JAMO_V_BASE) {
return U_SENTINEL;
}
b-=Hangul::JAMO_V_BASE; b-=Hangul::JAMO_V_BASE;
if(0<=b && b<Hangul::JAMO_V_COUNT) { if(b<Hangul::JAMO_V_COUNT) {
return return
(Hangul::HANGUL_BASE+ (Hangul::HANGUL_BASE+
((a-Hangul::JAMO_L_BASE)*Hangul::JAMO_V_COUNT+b)* ((a-Hangul::JAMO_L_BASE)*Hangul::JAMO_V_COUNT+b)*
@ -1400,8 +1403,11 @@ Normalizer2Impl::composePair(UChar32 a, UChar32 b) const {
return U_SENTINEL; return U_SENTINEL;
} }
} else if(isHangulLV(norm16)) { } else if(isHangulLV(norm16)) {
if (b <= Hangul::JAMO_T_BASE) {
return U_SENTINEL;
}
b-=Hangul::JAMO_T_BASE; b-=Hangul::JAMO_T_BASE;
if(0<b && b<Hangul::JAMO_T_COUNT) { // not b==0! if(b<Hangul::JAMO_T_COUNT) { // not b==0!
return a+b; return a+b;
} else { } else {
return U_SENTINEL; return U_SENTINEL;

View File

@ -141,12 +141,12 @@ public:
/** Constructs only; init() should be called. */ /** Constructs only; init() should be called. */
ReorderingBuffer(const Normalizer2Impl &ni, UnicodeString &dest) : ReorderingBuffer(const Normalizer2Impl &ni, UnicodeString &dest) :
impl(ni), str(dest), impl(ni), str(dest),
start(NULL), reorderStart(NULL), limit(NULL), start(nullptr), reorderStart(nullptr), limit(nullptr),
remainingCapacity(0), lastCC(0) {} remainingCapacity(0), lastCC(0) {}
/** Constructs, removes the string contents, and initializes for a small initial capacity. */ /** Constructs, removes the string contents, and initializes for a small initial capacity. */
ReorderingBuffer(const Normalizer2Impl &ni, UnicodeString &dest, UErrorCode &errorCode); ReorderingBuffer(const Normalizer2Impl &ni, UnicodeString &dest, UErrorCode &errorCode);
~ReorderingBuffer() { ~ReorderingBuffer() {
if(start!=NULL) { if (start != nullptr) {
str.releaseBuffer((int32_t)(limit-start)); str.releaseBuffer((int32_t)(limit-start));
} }
} }
@ -245,7 +245,7 @@ private:
*/ */
class U_COMMON_API Normalizer2Impl : public UObject { class U_COMMON_API Normalizer2Impl : public UObject {
public: public:
Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) { } Normalizer2Impl() : normTrie(nullptr), fCanonIterData(nullptr) {}
virtual ~Normalizer2Impl(); virtual ~Normalizer2Impl();
void init(const int32_t *inIndexes, const UCPTrie *inTrie, void init(const int32_t *inIndexes, const UCPTrie *inTrie,
@ -623,7 +623,7 @@ private:
const uint16_t *getMapping(uint16_t norm16) const { return extraData+(norm16>>OFFSET_SHIFT); } const uint16_t *getMapping(uint16_t norm16) const { return extraData+(norm16>>OFFSET_SHIFT); }
const uint16_t *getCompositionsListForDecompYes(uint16_t norm16) const { const uint16_t *getCompositionsListForDecompYes(uint16_t norm16) const {
if(norm16<JAMO_L || MIN_NORMAL_MAYBE_YES<=norm16) { if(norm16<JAMO_L || MIN_NORMAL_MAYBE_YES<=norm16) {
return NULL; return nullptr;
} else if(norm16<minMaybeYes) { } else if(norm16<minMaybeYes) {
return getMapping(norm16); // for yesYes; if Jamo L: harmless empty list return getMapping(norm16); // for yesYes; if Jamo L: harmless empty list
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@ -1498,7 +1498,6 @@ static void U_CALLCONV dataDirectoryInitFn() {
} }
u_setDataDirectory(path); u_setDataDirectory(path);
return;
} }
U_CAPI const char * U_EXPORT2 U_CAPI const char * U_EXPORT2
@ -1622,7 +1621,7 @@ static const char *uprv_getPOSIXIDForCategory(int category)
* of nullptr, will modify the libc behavior. * of nullptr, will modify the libc behavior.
*/ */
posixID = setlocale(category, nullptr); posixID = setlocale(category, nullptr);
if ((posixID == 0) if ((posixID == nullptr)
|| (uprv_strcmp("C", posixID) == 0) || (uprv_strcmp("C", posixID) == 0)
|| (uprv_strcmp("POSIX", posixID) == 0)) || (uprv_strcmp("POSIX", posixID) == 0))
{ {
@ -1636,16 +1635,16 @@ static const char *uprv_getPOSIXIDForCategory(int category)
posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE"); posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE");
if ((posixID == 0) || (posixID[0] == '\0')) { if ((posixID == 0) || (posixID[0] == '\0')) {
#else #else
if (posixID == 0) { if (posixID == nullptr) {
posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE"); posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE");
if (posixID == 0) { if (posixID == nullptr) {
#endif #endif
posixID = getenv("LANG"); posixID = getenv("LANG");
} }
} }
} }
} }
if ((posixID==0) if ((posixID == nullptr)
|| (uprv_strcmp("C", posixID) == 0) || (uprv_strcmp("C", posixID) == 0)
|| (uprv_strcmp("POSIX", posixID) == 0)) || (uprv_strcmp("POSIX", posixID) == 0))
{ {
@ -1665,7 +1664,7 @@ static const char *uprv_getPOSIXIDForCategory(int category)
static const char *uprv_getPOSIXIDForDefaultLocale() static const char *uprv_getPOSIXIDForDefaultLocale()
{ {
static const char* posixID = nullptr; static const char* posixID = nullptr;
if (posixID == 0) { if (posixID == nullptr) {
posixID = uprv_getPOSIXIDForCategory(LC_MESSAGES); posixID = uprv_getPOSIXIDForCategory(LC_MESSAGES);
} }
return posixID; return posixID;

View File

@ -1212,7 +1212,7 @@ RuleBasedBreakIterator::getLanguageBreakEngine(UChar32 c, const char* locale) {
fLanguageBreakEngines = new UStack(status); fLanguageBreakEngines = new UStack(status);
if (fLanguageBreakEngines == nullptr || U_FAILURE(status)) { if (fLanguageBreakEngines == nullptr || U_FAILURE(status)) {
delete fLanguageBreakEngines; delete fLanguageBreakEngines;
fLanguageBreakEngines = 0; fLanguageBreakEngines = nullptr;
return nullptr; return nullptr;
} }
} }
@ -1252,7 +1252,7 @@ RuleBasedBreakIterator::getLanguageBreakEngine(UChar32 c, const char* locale) {
U_ASSERT(!fLanguageBreakEngines->hasDeleter()); U_ASSERT(!fLanguageBreakEngines->hasDeleter());
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
delete fUnhandledBreakEngine; delete fUnhandledBreakEngine;
fUnhandledBreakEngine = 0; fUnhandledBreakEngine = nullptr;
return nullptr; return nullptr;
} }
} }

View File

@ -246,7 +246,6 @@ void RuleBasedBreakIterator::BreakCache::following(int32_t startPos, UErrorCode
fBI->fDone = false; fBI->fDone = false;
next(); next();
} }
return;
} }
@ -265,7 +264,6 @@ void RuleBasedBreakIterator::BreakCache::preceding(int32_t startPos, UErrorCode
current(); current();
} }
} }
return;
} }
@ -277,7 +275,6 @@ void RuleBasedBreakIterator::BreakCache::nextOL() {
fBI->fDone = !populateFollowing(); fBI->fDone = !populateFollowing();
fBI->fPosition = fTextIdx; fBI->fPosition = fTextIdx;
fBI->fRuleStatusIndex = fStatuses[fBufIdx]; fBI->fRuleStatusIndex = fStatuses[fBufIdx];
return;
} }
@ -297,7 +294,6 @@ void RuleBasedBreakIterator::BreakCache::previous(UErrorCode &status) {
fBI->fDone = (fBufIdx == initialBufIdx); fBI->fDone = (fBufIdx == initialBufIdx);
fBI->fPosition = fTextIdx; fBI->fPosition = fTextIdx;
fBI->fRuleStatusIndex = fStatuses[fBufIdx]; fBI->fRuleStatusIndex = fStatuses[fBufIdx];
return;
} }

View File

@ -123,19 +123,66 @@ RBBINode::~RBBINode() {
break; break;
default: default:
delete fLeftChild; // Avoid using a recursive implementation because of stack overflow problems.
// See bug ICU-22584.
// delete fLeftChild;
NRDeleteNode(fLeftChild);
fLeftChild = nullptr; fLeftChild = nullptr;
delete fRightChild; // delete fRightChild;
NRDeleteNode(fRightChild);
fRightChild = nullptr; fRightChild = nullptr;
} }
delete fFirstPosSet; delete fFirstPosSet;
delete fLastPosSet; delete fLastPosSet;
delete fFollowPos; delete fFollowPos;
} }
/**
* Non-recursive delete of a node + its children. Used from the node destructor
* instead of the more obvious recursive implementation to avoid problems with
* stack overflow with some perverse test rule data (from fuzzing).
*/
void RBBINode::NRDeleteNode(RBBINode *node) {
if (node == nullptr) {
return;
}
RBBINode *stopNode = node->fParent;
RBBINode *nextNode = node;
while (nextNode != stopNode && nextNode != nullptr) {
RBBINode *currentNode = nextNode;
if ((currentNode->fLeftChild == nullptr && currentNode->fRightChild == nullptr) ||
currentNode->fType == varRef || // varRef and setRef nodes do not
currentNode->fType == setRef) { // own their children nodes.
// CurrentNode is effectively a leaf node; it's safe to go ahead and delete it.
nextNode = currentNode->fParent;
if (nextNode) {
if (nextNode->fLeftChild == currentNode) {
nextNode->fLeftChild = nullptr;
} else if (nextNode->fRightChild == currentNode) {
nextNode->fRightChild = nullptr;
}
}
delete currentNode;
} else if (currentNode->fLeftChild) {
nextNode = currentNode->fLeftChild;
if (nextNode->fParent == nullptr) {
nextNode->fParent = currentNode;
// fParent isn't always set; do it now if not.
}
U_ASSERT(nextNode->fParent == currentNode);
} else if (currentNode->fRightChild) {
nextNode = currentNode->fRightChild;
if (nextNode->fParent == nullptr) {
nextNode->fParent = currentNode;
// fParent isn't always set; do it now if not.
}
U_ASSERT(nextNode->fParent == currentNode);
}
}
}
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// //
@ -192,7 +239,17 @@ RBBINode *RBBINode::cloneTree() {
// nested references are handled by cloneTree(), not here. // nested references are handled by cloneTree(), not here.
// //
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
RBBINode *RBBINode::flattenVariables() { constexpr int kRecursiveDepthLimit = 3500;
RBBINode *RBBINode::flattenVariables(UErrorCode& status, int depth) {
if (U_FAILURE(status)) {
return this;
}
// If the depth of the stack is too deep, we return U_INPUT_TOO_LONG_ERROR
// to avoid stack overflow crash.
if (depth > kRecursiveDepthLimit) {
status = U_INPUT_TOO_LONG_ERROR;
return this;
}
if (fType == varRef) { if (fType == varRef) {
RBBINode *retNode = fLeftChild->cloneTree(); RBBINode *retNode = fLeftChild->cloneTree();
if (retNode != nullptr) { if (retNode != nullptr) {
@ -204,11 +261,11 @@ RBBINode *RBBINode::flattenVariables() {
} }
if (fLeftChild != nullptr) { if (fLeftChild != nullptr) {
fLeftChild = fLeftChild->flattenVariables(); fLeftChild = fLeftChild->flattenVariables(status, depth+1);
fLeftChild->fParent = this; fLeftChild->fParent = this;
} }
if (fRightChild != nullptr) { if (fRightChild != nullptr) {
fRightChild = fRightChild->flattenVariables(); fRightChild = fRightChild->flattenVariables(status, depth+1);
fRightChild->fParent = this; fRightChild->fParent = this;
} }
return this; return this;

View File

@ -94,9 +94,10 @@ class RBBINode : public UMemory {
RBBINode(NodeType t); RBBINode(NodeType t);
RBBINode(const RBBINode &other); RBBINode(const RBBINode &other);
~RBBINode(); ~RBBINode();
static void NRDeleteNode(RBBINode *node);
RBBINode *cloneTree(); RBBINode *cloneTree();
RBBINode *flattenVariables(); RBBINode *flattenVariables(UErrorCode &status, int depth=0);
void flattenSets(); void flattenSets();
void findNodes(UVector *dest, RBBINode::NodeType kind, UErrorCode &status); void findNodes(UVector *dest, RBBINode::NodeType kind, UErrorCode &status);

View File

@ -86,7 +86,8 @@ RBBIRuleBuilder::RBBIRuleBuilder(const UnicodeString &rules,
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return; return;
} }
if(fSetBuilder == 0 || fScanner == 0 || fUSetNodes == 0 || fRuleStatusVals == 0) { if (fSetBuilder == nullptr || fScanner == nullptr ||
fUSetNodes == nullptr || fRuleStatusVals == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
} }
} }
@ -156,7 +157,7 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() {
int32_t statusTableSize = align8(fRuleStatusVals->size() * sizeof(int32_t)); int32_t statusTableSize = align8(fRuleStatusVals->size() * sizeof(int32_t));
int32_t rulesLengthInUTF8 = 0; int32_t rulesLengthInUTF8 = 0;
u_strToUTF8WithSub(0, 0, &rulesLengthInUTF8, u_strToUTF8WithSub(nullptr, 0, &rulesLengthInUTF8,
fStrippedRules.getBuffer(), fStrippedRules.length(), fStrippedRules.getBuffer(), fStrippedRules.length(),
0xfffd, nullptr, fStatus); 0xfffd, nullptr, fStatus);
*fStatus = U_ZERO_ERROR; *fStatus = U_ZERO_ERROR;

View File

@ -289,6 +289,9 @@ UBool RBBIRuleScanner::doParseActions(int32_t action)
// Terminate expression, leaves expression parse tree rooted in TOS node. // Terminate expression, leaves expression parse tree rooted in TOS node.
fixOpStack(RBBINode::precStart); fixOpStack(RBBINode::precStart);
if (U_FAILURE(*fRB->fStatus)) {
break;
}
RBBINode *startExprNode = fNodeStack[fNodeStackPtr-2]; RBBINode *startExprNode = fNodeStack[fNodeStackPtr-2];
RBBINode *varRefNode = fNodeStack[fNodeStackPtr-1]; RBBINode *varRefNode = fNodeStack[fNodeStackPtr-1];
@ -312,6 +315,11 @@ UBool RBBIRuleScanner::doParseActions(int32_t action)
UErrorCode t = *fRB->fStatus; UErrorCode t = *fRB->fStatus;
*fRB->fStatus = U_ZERO_ERROR; *fRB->fStatus = U_ZERO_ERROR;
error(t); error(t);
// When adding $variableRef to the symbol table fail, Delete
// both nodes because deleting varRefNode will not delete
// RHSExprNode internally.
delete RHSExprNode;
delete varRefNode;
} }
// Clean up the stack. // Clean up the stack.
@ -522,7 +530,13 @@ UBool RBBIRuleScanner::doParseActions(int32_t action)
n = fNodeStack[fNodeStackPtr]; n = fNodeStack[fNodeStackPtr];
uint32_t v = u_charDigitValue(fC.fChar); uint32_t v = u_charDigitValue(fC.fChar);
U_ASSERT(v < 10); U_ASSERT(v < 10);
n->fVal = n->fVal*10 + v; int64_t updated = static_cast<int64_t>(n->fVal)*10 + v;
// Avoid overflow n->fVal
if (updated > INT32_MAX) {
error(U_BRK_RULE_SYNTAX);
break;
}
n->fVal = static_cast<int32_t>(updated);
break; break;
} }
@ -762,6 +776,7 @@ void RBBIRuleScanner::findSetFor(const UnicodeString &s, RBBINode *node, Unicode
RBBINode *usetNode = new RBBINode(RBBINode::uset); RBBINode *usetNode = new RBBINode(RBBINode::uset);
if (usetNode == nullptr) { if (usetNode == nullptr) {
error(U_MEMORY_ALLOCATION_ERROR); error(U_MEMORY_ALLOCATION_ERROR);
delete setToAdopt;
return; return;
} }
usetNode->fInputSet = setToAdopt; usetNode->fInputSet = setToAdopt;
@ -796,8 +811,6 @@ void RBBIRuleScanner::findSetFor(const UnicodeString &s, RBBINode *node, Unicode
el->key = tkey; el->key = tkey;
el->val = usetNode; el->val = usetNode;
uhash_put(fSetTable, el->key, el, fRB->fStatus); uhash_put(fSetTable, el->key, el, fRB->fStatus);
return;
} }
@ -926,6 +939,9 @@ void RBBIRuleScanner::nextChar(RBBIRuleChar &c) {
} }
} }
if (c.fChar == (UChar32)-1) {
return;
}
if (fQuoteMode) { if (fQuoteMode) {
c.fEscaped = true; c.fEscaped = true;
} }
@ -1199,7 +1215,6 @@ RBBINode *RBBIRuleScanner::pushNewNode(RBBINode::NodeType t) {
// //
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void RBBIRuleScanner::scanSet() { void RBBIRuleScanner::scanSet() {
UnicodeSet *uset;
ParsePosition pos; ParsePosition pos;
int startPos; int startPos;
int i; int i;
@ -1211,12 +1226,12 @@ void RBBIRuleScanner::scanSet() {
pos.setIndex(fScanIndex); pos.setIndex(fScanIndex);
startPos = fScanIndex; startPos = fScanIndex;
UErrorCode localStatus = U_ZERO_ERROR; UErrorCode localStatus = U_ZERO_ERROR;
uset = new UnicodeSet(); LocalPointer<UnicodeSet> uset(new UnicodeSet(), localStatus);
if (uset == nullptr) { if (U_FAILURE(localStatus)) {
localStatus = U_MEMORY_ALLOCATION_ERROR; error(localStatus);
} else { return;
uset->applyPatternIgnoreSpace(fRB->fRules, pos, fSymbolTable, localStatus);
} }
uset->applyPatternIgnoreSpace(fRB->fRules, pos, fSymbolTable, localStatus);
if (U_FAILURE(localStatus)) { if (U_FAILURE(localStatus)) {
// TODO: Get more accurate position of the error from UnicodeSet's return info. // TODO: Get more accurate position of the error from UnicodeSet's return info.
// UnicodeSet appears to not be reporting correctly at this time. // UnicodeSet appears to not be reporting correctly at this time.
@ -1224,20 +1239,22 @@ void RBBIRuleScanner::scanSet() {
RBBIDebugPrintf("UnicodeSet parse position.ErrorIndex = %d\n", pos.getIndex()); RBBIDebugPrintf("UnicodeSet parse position.ErrorIndex = %d\n", pos.getIndex());
#endif #endif
error(localStatus); error(localStatus);
delete uset;
return; return;
} }
// Verify that the set contains at least one code point. // Verify that the set contains at least one code point.
// //
U_ASSERT(uset!=nullptr); U_ASSERT(uset.isValid());
if (uset->isEmpty()) { UnicodeSet tempSet(*uset);
// Use tempSet to handle the case that the UnicodeSet contains
// only string element, such as [{ab}] and treat it as empty set.
tempSet.removeAllStrings();
if (tempSet.isEmpty()) {
// This set is empty. // This set is empty.
// Make it an error, because it almost certainly is not what the user wanted. // Make it an error, because it almost certainly is not what the user wanted.
// Also, avoids having to think about corner cases in the tree manipulation code // Also, avoids having to think about corner cases in the tree manipulation code
// that occurs later on. // that occurs later on.
error(U_BRK_RULE_EMPTY_SET); error(U_BRK_RULE_EMPTY_SET);
delete uset;
return; return;
} }
@ -1246,7 +1263,7 @@ void RBBIRuleScanner::scanSet() {
// Don't just set fScanIndex because the line/char positions maintained // Don't just set fScanIndex because the line/char positions maintained
// for error reporting would be thrown off. // for error reporting would be thrown off.
i = pos.getIndex(); i = pos.getIndex();
for (;;) { for (;U_SUCCESS(*fRB->fStatus);) {
if (fNextIndex >= i) { if (fNextIndex >= i) {
break; break;
} }
@ -1269,7 +1286,7 @@ void RBBIRuleScanner::scanSet() {
// character categories for run time engine. // character categories for run time engine.
// - Eliminates mulitiple instances of the same set. // - Eliminates mulitiple instances of the same set.
// - Creates a new uset node if necessary (if this isn't a duplicate.) // - Creates a new uset node if necessary (if this isn't a duplicate.)
findSetFor(n->fText, n, uset); findSetFor(n->fText, n, uset.orphan());
} }
} }

View File

@ -122,7 +122,7 @@ const UnicodeFunctor *RBBISymbolTable::lookupMatcher(UChar32 ch) const
RBBISymbolTable *This = (RBBISymbolTable *)this; // cast off const RBBISymbolTable *This = (RBBISymbolTable *)this; // cast off const
if (ch == 0xffff) { if (ch == 0xffff) {
retVal = fCachedSetLookup; retVal = fCachedSetLookup;
This->fCachedSetLookup = 0; This->fCachedSetLookup = nullptr;
} }
return retVal; return retVal;
} }

View File

@ -81,7 +81,10 @@ void RBBITableBuilder::buildForwardTable() {
// Walk through the tree, replacing any references to $variables with a copy of the // Walk through the tree, replacing any references to $variables with a copy of the
// parse tree for the substitution expression. // parse tree for the substitution expression.
// //
fTree = fTree->flattenVariables(); fTree = fTree->flattenVariables(*fStatus, 0);
if (U_FAILURE(*fStatus)) {
return;
}
#ifdef RBBI_DEBUG #ifdef RBBI_DEBUG
if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ftree")) { if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ftree")) {
RBBIDebugPuts("\nParse tree after flattening variable references."); RBBIDebugPuts("\nParse tree after flattening variable references.");

View File

@ -179,7 +179,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ResourceBundle)
ResourceBundle::ResourceBundle(UErrorCode &err) ResourceBundle::ResourceBundle(UErrorCode &err)
:UObject(), fLocale(nullptr) :UObject(), fLocale(nullptr)
{ {
fResource = ures_open(0, Locale::getDefault().getName(), &err); fResource = ures_open(nullptr, Locale::getDefault().getName(), &err);
} }
ResourceBundle::ResourceBundle(const ResourceBundle &other) ResourceBundle::ResourceBundle(const ResourceBundle &other)
@ -188,7 +188,7 @@ ResourceBundle::ResourceBundle(const ResourceBundle &other)
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
if (other.fResource) { if (other.fResource) {
fResource = ures_copyResb(0, other.fResource, &status); fResource = ures_copyResb(nullptr, other.fResource, &status);
} else { } else {
/* Copying a bad resource bundle */ /* Copying a bad resource bundle */
fResource = nullptr; fResource = nullptr;
@ -199,7 +199,7 @@ ResourceBundle::ResourceBundle(UResourceBundle *res, UErrorCode& err)
:UObject(), fLocale(nullptr) :UObject(), fLocale(nullptr)
{ {
if (res) { if (res) {
fResource = ures_copyResb(0, res, &err); fResource = ures_copyResb(nullptr, res, &err);
} else { } else {
/* Copying a bad resource bundle */ /* Copying a bad resource bundle */
fResource = nullptr; fResource = nullptr;
@ -218,7 +218,7 @@ ResourceBundle& ResourceBundle::operator=(const ResourceBundle& other)
if(this == &other) { if(this == &other) {
return *this; return *this;
} }
if(fResource != 0) { if (fResource != nullptr) {
ures_close(fResource); ures_close(fResource);
fResource = nullptr; fResource = nullptr;
} }
@ -228,7 +228,7 @@ ResourceBundle& ResourceBundle::operator=(const ResourceBundle& other)
} }
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
if (other.fResource) { if (other.fResource) {
fResource = ures_copyResb(0, other.fResource, &status); fResource = ures_copyResb(nullptr, other.fResource, &status);
} else { } else {
/* Copying a bad resource bundle */ /* Copying a bad resource bundle */
fResource = nullptr; fResource = nullptr;
@ -238,12 +238,10 @@ ResourceBundle& ResourceBundle::operator=(const ResourceBundle& other)
ResourceBundle::~ResourceBundle() ResourceBundle::~ResourceBundle()
{ {
if(fResource != 0) { if (fResource != nullptr) {
ures_close(fResource); ures_close(fResource);
} }
if(fLocale != nullptr) { delete fLocale;
delete(fLocale);
}
} }
ResourceBundle * ResourceBundle *
@ -311,7 +309,7 @@ ResourceBundle ResourceBundle::getNext(UErrorCode& status) {
UnicodeString ResourceBundle::getNextString(UErrorCode& status) { UnicodeString ResourceBundle::getNextString(UErrorCode& status) {
int32_t len = 0; int32_t len = 0;
const char16_t* r = ures_getNextString(fResource, &len, 0, &status); const char16_t* r = ures_getNextString(fResource, &len, nullptr, &status);
return UnicodeString(true, r, len); return UnicodeString(true, r, len);
} }

View File

@ -27,12 +27,12 @@ RuleCharacterIterator::RuleCharacterIterator(const UnicodeString& theText, const
text(theText), text(theText),
pos(thePos), pos(thePos),
sym(theSym), sym(theSym),
buf(0), buf(nullptr),
bufPos(0) bufPos(0)
{} {}
UBool RuleCharacterIterator::atEnd() const { UBool RuleCharacterIterator::atEnd() const {
return buf == 0 && pos.getIndex() == text.length(); return buf == nullptr && pos.getIndex() == text.length();
} }
UChar32 RuleCharacterIterator::next(int32_t options, UBool& isEscaped, UErrorCode& ec) { UChar32 RuleCharacterIterator::next(int32_t options, UBool& isEscaped, UErrorCode& ec) {
@ -45,8 +45,8 @@ UChar32 RuleCharacterIterator::next(int32_t options, UBool& isEscaped, UErrorCod
c = _current(); c = _current();
_advance(U16_LENGTH(c)); _advance(U16_LENGTH(c));
if (c == SymbolTable::SYMBOL_REF && buf == 0 && if (c == SymbolTable::SYMBOL_REF && buf == nullptr &&
(options & PARSE_VARIABLES) != 0 && sym != 0) { (options & PARSE_VARIABLES) != 0 && sym != nullptr) {
UnicodeString name = sym->parseReference(text, pos, text.length()); UnicodeString name = sym->parseReference(text, pos, text.length());
// If name is empty there was an isolated SYMBOL_REF; // If name is empty there was an isolated SYMBOL_REF;
// return it. Caller must be prepared for this. // return it. Caller must be prepared for this.
@ -55,13 +55,13 @@ UChar32 RuleCharacterIterator::next(int32_t options, UBool& isEscaped, UErrorCod
} }
bufPos = 0; bufPos = 0;
buf = sym->lookup(name); buf = sym->lookup(name);
if (buf == 0) { if (buf == nullptr) {
ec = U_UNDEFINED_VARIABLE; ec = U_UNDEFINED_VARIABLE;
return DONE; return DONE;
} }
// Handle empty variable value // Handle empty variable value
if (buf->length() == 0) { if (buf->length() == 0) {
buf = 0; buf = nullptr;
} }
continue; continue;
} }
@ -114,7 +114,7 @@ UnicodeString& RuleCharacterIterator::lookahead(UnicodeString& result, int32_t m
if (maxLookAhead < 0) { if (maxLookAhead < 0) {
maxLookAhead = 0x7FFFFFFF; maxLookAhead = 0x7FFFFFFF;
} }
if (buf != 0) { if (buf != nullptr) {
buf->extract(bufPos, maxLookAhead, result); buf->extract(bufPos, maxLookAhead, result);
} else { } else {
text.extract(pos.getIndex(), maxLookAhead, result); text.extract(pos.getIndex(), maxLookAhead, result);
@ -135,7 +135,7 @@ UnicodeString& RuleCharacterIterator::toString(UnicodeString& result) const {
*/ */
UChar32 RuleCharacterIterator::_current() const { UChar32 RuleCharacterIterator::_current() const {
if (buf != 0) { if (buf != nullptr) {
return buf->char32At(bufPos); return buf->char32At(bufPos);
} else { } else {
int i = pos.getIndex(); int i = pos.getIndex();
@ -144,10 +144,10 @@ UChar32 RuleCharacterIterator::_current() const {
} }
void RuleCharacterIterator::_advance(int32_t count) { void RuleCharacterIterator::_advance(int32_t count) {
if (buf != 0) { if (buf != nullptr) {
bufPos += count; bufPos += count;
if (bufPos == buf->length()) { if (bufPos == buf->length()) {
buf = 0; buf = nullptr;
} }
} else { } else {
pos.setIndex(pos.getIndex() + count); pos.setIndex(pos.getIndex() + count);

View File

@ -224,7 +224,7 @@ private:
}; };
inline UBool RuleCharacterIterator::inVariable() const { inline UBool RuleCharacterIterator::inVariable() const {
return buf != 0; return buf != nullptr;
} }
U_NAMESPACE_END U_NAMESPACE_END

View File

@ -244,7 +244,6 @@ ubidi_setLine(const UBiDi *pParaBiDi,
} }
} }
pLineBiDi->pParaBiDi=pParaBiDi; /* mark successful setLine */ pLineBiDi->pParaBiDi=pParaBiDi; /* mark successful setLine */
return;
} }
U_CAPI UBiDiLevel U_EXPORT2 U_CAPI UBiDiLevel U_EXPORT2

View File

@ -38,9 +38,9 @@ ubrk_open(UBreakIteratorType type,
UErrorCode *status) UErrorCode *status)
{ {
if(U_FAILURE(*status)) return 0; if (U_FAILURE(*status)) return nullptr;
BreakIterator *result = 0; BreakIterator *result = nullptr;
switch(type) { switch(type) {
@ -70,11 +70,11 @@ ubrk_open(UBreakIteratorType type,
// check for allocation error // check for allocation error
if (U_FAILURE(*status)) { if (U_FAILURE(*status)) {
return 0; return nullptr;
} }
if(result == 0) { if (result == nullptr) {
*status = U_MEMORY_ALLOCATION_ERROR; *status = U_MEMORY_ALLOCATION_ERROR;
return 0; return nullptr;
} }
@ -102,14 +102,14 @@ ubrk_openRules( const char16_t *rules,
UErrorCode *status) { UErrorCode *status) {
if (status == nullptr || U_FAILURE(*status)){ if (status == nullptr || U_FAILURE(*status)){
return 0; return nullptr;
} }
BreakIterator *result = 0; BreakIterator *result = nullptr;
UnicodeString ruleString(rules, rulesLength); UnicodeString ruleString(rules, rulesLength);
result = RBBIRuleBuilder::createRuleBasedBreakIterator(ruleString, parseErr, *status); result = RBBIRuleBuilder::createRuleBasedBreakIterator(ruleString, parseErr, *status);
if(U_FAILURE(*status)) { if(U_FAILURE(*status)) {
return 0; return nullptr;
} }
UBreakIterator *uBI = (UBreakIterator *)result; UBreakIterator *uBI = (UBreakIterator *)result;

View File

@ -357,7 +357,7 @@ enum {
/* definitions for 16-bit case properties word ------------------------------ */ /* definitions for 16-bit case properties word ------------------------------ */
U_CFUNC const UTrie2 * U_EXPORT2 U_CFUNC const UTrie2 * U_EXPORT2
ucase_getTrie(); ucase_getTrie(void);
/* 2-bit constants for types of cased characters */ /* 2-bit constants for types of cased characters */
#define UCASE_TYPE_MASK 3 #define UCASE_TYPE_MASK 3

View File

@ -41,7 +41,6 @@
#include "uassert.h" #include "uassert.h"
#include "ucase.h" #include "ucase.h"
#include "ucasemap_imp.h" #include "ucasemap_imp.h"
#include "ustr_imp.h"
U_NAMESPACE_USE U_NAMESPACE_USE
@ -917,21 +916,20 @@ ucasemap_mapUTF8(int32_t caseLocale, uint32_t options, UCASEMAP_BREAK_ITERATOR_P
return 0; return 0;
} }
CheckedArrayByteSink sink(dest, destCapacity);
if (edits != nullptr && (options & U_EDITS_NO_RESET) == 0) { if (edits != nullptr && (options & U_EDITS_NO_RESET) == 0) {
edits->reset(); edits->reset();
} }
int32_t reslen = ByteSinkUtil::viaByteSinkToTerminatedChars(
dest, destCapacity,
[&](ByteSink& sink, UErrorCode& status) {
stringCaseMapper(caseLocale, options, UCASEMAP_BREAK_ITERATOR stringCaseMapper(caseLocale, options, UCASEMAP_BREAK_ITERATOR
(const uint8_t *)src, srcLength, sink, edits, errorCode); (const uint8_t *)src, srcLength, sink, edits, status);
sink.Flush(); },
if (U_SUCCESS(errorCode)) { errorCode);
if (sink.Overflowed()) { if (U_SUCCESS(errorCode) && edits != nullptr) {
errorCode = U_BUFFER_OVERFLOW_ERROR;
} else if (edits != nullptr) {
edits->copyErrorTo(errorCode); edits->copyErrorTo(errorCode);
} }
} return reslen;
return u_terminateChars(dest, destCapacity, sink.NumberOfBytesAppended(), &errorCode);
} }
/* public API functions */ /* public API functions */

File diff suppressed because it is too large Load Diff

View File

@ -20,14 +20,14 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UCharCharacterIterator)
UCharCharacterIterator::UCharCharacterIterator() UCharCharacterIterator::UCharCharacterIterator()
: CharacterIterator(), : CharacterIterator(),
text(0) text(nullptr)
{ {
// never default construct! // never default construct!
} }
UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr, UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
int32_t length) int32_t length)
: CharacterIterator(textPtr != 0 ? (length>=0 ? length : u_strlen(textPtr)) : 0), : CharacterIterator(textPtr != nullptr ? (length >= 0 ? length : u_strlen(textPtr)) : 0),
text(textPtr) text(textPtr)
{ {
} }
@ -35,7 +35,7 @@ UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr, UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
int32_t length, int32_t length,
int32_t position) int32_t position)
: CharacterIterator(textPtr != 0 ? (length>=0 ? length : u_strlen(textPtr)) : 0, position), : CharacterIterator(textPtr != nullptr ? (length >= 0 ? length : u_strlen(textPtr)) : 0, position),
text(textPtr) text(textPtr)
{ {
} }
@ -45,7 +45,8 @@ UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
int32_t textBegin, int32_t textBegin,
int32_t textEnd, int32_t textEnd,
int32_t position) int32_t position)
: CharacterIterator(textPtr != 0 ? (length>=0 ? length : u_strlen(textPtr)) : 0, textBegin, textEnd, position), : CharacterIterator(textPtr != nullptr ? (length >= 0 ? length : u_strlen(textPtr)) : 0,
textBegin, textEnd, position),
text(textPtr) text(textPtr)
{ {
} }
@ -352,7 +353,7 @@ UCharCharacterIterator::move32(int32_t delta, CharacterIterator::EOrigin origin)
void UCharCharacterIterator::setText(ConstChar16Ptr newText, void UCharCharacterIterator::setText(ConstChar16Ptr newText,
int32_t newTextLength) { int32_t newTextLength) {
text = newText; text = newText;
if(newText == 0 || newTextLength < 0) { if (newText == nullptr || newTextLength < 0) {
newTextLength = 0; newTextLength = 0;
} }
end = textLength = newTextLength; end = textLength = newTextLength;

View File

@ -473,8 +473,6 @@ ucnv_setSubstChars (UConverter * converter,
* we set subChar1 to 0. * we set subChar1 to 0.
*/ */
converter->subChar1 = 0; converter->subChar1 = 0;
return;
} }
U_CAPI void U_EXPORT2 U_CAPI void U_EXPORT2
@ -1754,7 +1752,7 @@ ucnv_fromUChars(UConverter *cnv,
destLimit=dest+destCapacity; destLimit=dest+destCapacity;
/* perform the conversion */ /* perform the conversion */
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, true, pErrorCode); ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
destLength=(int32_t)(dest-originalDest); destLength=(int32_t)(dest-originalDest);
/* if an overflow occurs, then get the preflighting length */ /* if an overflow occurs, then get the preflighting length */
@ -1765,7 +1763,7 @@ ucnv_fromUChars(UConverter *cnv,
do { do {
dest=buffer; dest=buffer;
*pErrorCode=U_ZERO_ERROR; *pErrorCode=U_ZERO_ERROR;
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, true, pErrorCode); ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
destLength+=(int32_t)(dest-buffer); destLength+=(int32_t)(dest-buffer);
} while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR); } while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
} }
@ -1810,7 +1808,7 @@ ucnv_toUChars(UConverter *cnv,
destLimit=dest+destCapacity; destLimit=dest+destCapacity;
/* perform the conversion */ /* perform the conversion */
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, true, pErrorCode); ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
destLength=(int32_t)(dest-originalDest); destLength=(int32_t)(dest-originalDest);
/* if an overflow occurs, then get the preflighting length */ /* if an overflow occurs, then get the preflighting length */
@ -1822,7 +1820,7 @@ ucnv_toUChars(UConverter *cnv,
do { do {
dest=buffer; dest=buffer;
*pErrorCode=U_ZERO_ERROR; *pErrorCode=U_ZERO_ERROR;
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, true, pErrorCode); ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
destLength+=(int32_t)(dest-buffer); destLength+=(int32_t)(dest-buffer);
} }
while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR); while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);

View File

@ -109,7 +109,6 @@ UCNV_FROM_U_CALLBACK_STOP (
*err = U_ZERO_ERROR; *err = U_ZERO_ERROR;
} }
/* the caller must have set the error code accordingly */ /* the caller must have set the error code accordingly */
return;
} }
@ -125,7 +124,6 @@ UCNV_TO_U_CALLBACK_STOP (
{ {
/* the caller must have set the error code accordingly */ /* the caller must have set the error code accordingly */
(void)context; (void)toUArgs; (void)codePoints; (void)length; (void)reason; (void)err; (void)context; (void)toUArgs; (void)codePoints; (void)length; (void)reason; (void)err;
return;
} }
U_CAPI void U_EXPORT2 U_CAPI void U_EXPORT2
@ -353,8 +351,6 @@ UCNV_FROM_U_CALLBACK_ESCAPE (
*err = err2; *err = err2;
return; return;
} }
return;
} }

View File

@ -455,7 +455,6 @@ unicodeMode:
pArgs->source=(const char *)source; pArgs->source=(const char *)source;
pArgs->target=target; pArgs->target=target;
pArgs->offsets=offsets; pArgs->offsets=offsets;
return;
} }
static void U_CALLCONV static void U_CALLCONV
@ -731,7 +730,6 @@ unicodeMode:
pArgs->source=source; pArgs->source=source;
pArgs->target=(char *)target; pArgs->target=(char *)target;
pArgs->offsets=offsets; pArgs->offsets=offsets;
return;
} }
static const char * U_CALLCONV static const char * U_CALLCONV
@ -1156,7 +1154,6 @@ endloop:
pArgs->source=(const char *)source; pArgs->source=(const char *)source;
pArgs->target=target; pArgs->target=target;
pArgs->offsets=offsets; pArgs->offsets=offsets;
return;
} }
static void U_CALLCONV static void U_CALLCONV
@ -1443,7 +1440,6 @@ unicodeMode:
pArgs->source=source; pArgs->source=source;
pArgs->target=(char *)target; pArgs->target=(char *)target;
pArgs->offsets=offsets; pArgs->offsets=offsets;
return;
} }
U_CDECL_END U_CDECL_END

View File

@ -1165,7 +1165,6 @@ endloop:
pArgs->source=(const char *)source; pArgs->source=(const char *)source;
pArgs->target=target; pArgs->target=target;
pArgs->offsets=offsets; pArgs->offsets=offsets;
return;
} }
/* /*
@ -1363,7 +1362,6 @@ endloop:
/* write back the updated pointers */ /* write back the updated pointers */
pArgs->source=(const char *)source; pArgs->source=(const char *)source;
pArgs->target=target; pArgs->target=target;
return;
} }
/* miscellaneous ------------------------------------------------------------ */ /* miscellaneous ------------------------------------------------------------ */

View File

@ -1537,12 +1537,12 @@ _ISCII_SafeClone(const UConverter *cnv,
int32_t bufferSizeNeeded = sizeof(struct cloneISCIIStruct); int32_t bufferSizeNeeded = sizeof(struct cloneISCIIStruct);
if (U_FAILURE(*status)) { if (U_FAILURE(*status)) {
return 0; return nullptr;
} }
if (*pBufferSize == 0) { /* 'preflighting' request - set needed size into *pBufferSize */ if (*pBufferSize == 0) { /* 'preflighting' request - set needed size into *pBufferSize */
*pBufferSize = bufferSizeNeeded; *pBufferSize = bufferSizeNeeded;
return 0; return nullptr;
} }
localClone = (struct cloneISCIIStruct *)stackBuffer; localClone = (struct cloneISCIIStruct *)stackBuffer;

View File

@ -572,7 +572,6 @@ endloop:
pArgs->source=(const char *)source; pArgs->source=(const char *)source;
pArgs->target=target; pArgs->target=target;
pArgs->offsets=offsets; pArgs->offsets=offsets;
return;
} }
/* /*
@ -864,7 +863,6 @@ endloop:
/* write back the updated pointers */ /* write back the updated pointers */
pArgs->source=(const char *)source; pArgs->source=(const char *)source;
pArgs->target=target; pArgs->target=target;
return;
} }
U_CDECL_END U_CDECL_END
/* SCSU-from-Unicode conversion functions ----------------------------------- */ /* SCSU-from-Unicode conversion functions ----------------------------------- */
@ -1978,12 +1976,12 @@ _SCSUSafeClone(const UConverter *cnv,
int32_t bufferSizeNeeded = sizeof(struct cloneSCSUStruct); int32_t bufferSizeNeeded = sizeof(struct cloneSCSUStruct);
if (U_FAILURE(*status)){ if (U_FAILURE(*status)){
return 0; return nullptr;
} }
if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */ if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
*pBufferSize = bufferSizeNeeded; *pBufferSize = bufferSizeNeeded;
return 0; return nullptr;
} }
localClone = (struct cloneSCSUStruct *)stackBuffer; localClone = (struct cloneSCSUStruct *)stackBuffer;

View File

@ -22,7 +22,6 @@
#include "unicode/usetiter.h" #include "unicode/usetiter.h"
#include "unicode/utf16.h" #include "unicode/utf16.h"
#include "ustr_imp.h" #include "ustr_imp.h"
#include "bytesinkutil.h"
#include "charstr.h" #include "charstr.h"
#include "cmemory.h" #include "cmemory.h"
#include "cstring.h" #include "cstring.h"
@ -296,7 +295,7 @@ myUCharsToChars(char* resultOfLen4, const char16_t* currency) {
static const int32_t* static const int32_t*
_findMetaData(const char16_t* currency, UErrorCode& ec) { _findMetaData(const char16_t* currency, UErrorCode& ec) {
if (currency == 0 || *currency == 0) { if (currency == nullptr || *currency == 0) {
if (U_SUCCESS(ec)) { if (U_SUCCESS(ec)) {
ec = U_ILLEGAL_ARGUMENT_ERROR; ec = U_ILLEGAL_ARGUMENT_ERROR;
} }
@ -349,10 +348,10 @@ _findMetaData(const char16_t* currency, UErrorCode& ec) {
// ------------------------------------- // -------------------------------------
static void static CharString
idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCode* ec) idForLocale(const char* locale, UErrorCode* ec)
{ {
ulocimp_getRegionForSupplementalData(locale, false, countryAndVariant, capacity, ec); return ulocimp_getRegionForSupplementalData(locale, false, *ec);
} }
// ------------------------------------------ // ------------------------------------------
@ -371,7 +370,7 @@ U_CDECL_END
struct CReg; struct CReg;
static UMutex gCRegLock; static UMutex gCRegLock;
static CReg* gCRegHead = 0; static CReg* gCRegHead = nullptr;
struct CReg : public icu::UMemory { struct CReg : public icu::UMemory {
CReg *next; CReg *next;
@ -379,7 +378,7 @@ struct CReg : public icu::UMemory {
char id[ULOC_FULLNAME_CAPACITY]; char id[ULOC_FULLNAME_CAPACITY];
CReg(const char16_t* _iso, const char* _id) CReg(const char16_t* _iso, const char* _id)
: next(0) : next(nullptr)
{ {
int32_t len = (int32_t)uprv_strlen(_id); int32_t len = (int32_t)uprv_strlen(_id);
if (len > (int32_t)(sizeof(id)-1)) { if (len > (int32_t)(sizeof(id)-1)) {
@ -408,7 +407,7 @@ struct CReg : public icu::UMemory {
} }
*status = U_MEMORY_ALLOCATION_ERROR; *status = U_MEMORY_ALLOCATION_ERROR;
} }
return 0; return nullptr;
} }
static UBool unreg(UCurrRegistryKey key) { static UBool unreg(UCurrRegistryKey key) {
@ -464,9 +463,8 @@ U_CAPI UCurrRegistryKey U_EXPORT2
ucurr_register(const char16_t* isoCode, const char* locale, UErrorCode *status) ucurr_register(const char16_t* isoCode, const char* locale, UErrorCode *status)
{ {
if (status && U_SUCCESS(*status)) { if (status && U_SUCCESS(*status)) {
char id[ULOC_FULLNAME_CAPACITY]; CharString id = idForLocale(locale, status);
idForLocale(locale, id, sizeof(id), status); return CReg::reg(isoCode, id.data(), status);
return CReg::reg(isoCode, id, status);
} }
return nullptr; return nullptr;
} }
@ -524,11 +522,7 @@ ucurr_forLocale(const char* locale,
} }
UErrorCode localStatus = U_ZERO_ERROR; UErrorCode localStatus = U_ZERO_ERROR;
CharString currency; CharString currency = ulocimp_getKeywordValue(locale, "currency", localStatus);
{
CharStringByteSink sink(&currency);
ulocimp_getKeywordValue(locale, "currency", sink, &localStatus);
}
int32_t resLen = currency.length(); int32_t resLen = currency.length();
if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency.data(), resLen)) { if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency.data(), resLen)) {
@ -540,14 +534,13 @@ ucurr_forLocale(const char* locale,
} }
// get country or country_variant in `id' // get country or country_variant in `id'
char id[ULOC_FULLNAME_CAPACITY]; CharString id = idForLocale(locale, ec);
idForLocale(locale, id, UPRV_LENGTHOF(id), ec);
if (U_FAILURE(*ec)) { if (U_FAILURE(*ec)) {
return 0; return 0;
} }
#if !UCONFIG_NO_SERVICE #if !UCONFIG_NO_SERVICE
const char16_t* result = CReg::get(id); const char16_t* result = CReg::get(id.data());
if (result) { if (result) {
if(buffCapacity > u_strlen(result)) { if(buffCapacity > u_strlen(result)) {
u_strcpy(buff, result); u_strcpy(buff, result);
@ -557,13 +550,13 @@ ucurr_forLocale(const char* locale,
} }
#endif #endif
// Remove variants, which is only needed for registration. // Remove variants, which is only needed for registration.
char *idDelim = uprv_strchr(id, VAR_DELIM); char *idDelim = uprv_strchr(id.data(), VAR_DELIM);
if (idDelim) { if (idDelim) {
idDelim[0] = 0; id.truncate(idDelim - id.data());
} }
const char16_t* s = nullptr; // Currency code from data file. const char16_t* s = nullptr; // Currency code from data file.
if (id[0] == 0) { if (id.isEmpty()) {
// No point looking in the data for an empty string. // No point looking in the data for an empty string.
// This is what we would get. // This is what we would get.
localStatus = U_MISSING_RESOURCE_ERROR; localStatus = U_MISSING_RESOURCE_ERROR;
@ -572,7 +565,7 @@ ucurr_forLocale(const char* locale,
localStatus = U_ZERO_ERROR; localStatus = U_ZERO_ERROR;
UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus); UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus);
// https://unicode-org.atlassian.net/browse/ICU-21997 // https://unicode-org.atlassian.net/browse/ICU-21997
// Prefer to use currencies that are legal tender. // Prefer to use currencies that are legal tender.
if (U_SUCCESS(localStatus)) { if (U_SUCCESS(localStatus)) {
@ -602,13 +595,9 @@ ucurr_forLocale(const char* locale,
ures_close(countryArray); ures_close(countryArray);
} }
if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) { if ((U_FAILURE(localStatus)) && strchr(id.data(), '_') != nullptr) {
// We don't know about it. Check to see if we support the variant. // We don't know about it. Check to see if we support the variant.
CharString parent; CharString parent = ulocimp_getParent(locale, *ec);
{
CharStringByteSink sink(&parent);
ulocimp_getParent(locale, sink, ec);
}
*ec = U_USING_FALLBACK_WARNING; *ec = U_USING_FALLBACK_WARNING;
// TODO: Loop over the parent rather than recursing and // TODO: Loop over the parent rather than recursing and
// looking again for a currency keyword. // looking again for a currency keyword.
@ -647,10 +636,7 @@ static UBool fallback(CharString& loc) {
loc.truncate(3); loc.truncate(3);
loc.append("001", status); loc.append("001", status);
} else { } else {
CharString tmp; loc = ulocimp_getParent(loc.data(), status);
CharStringByteSink sink(&tmp);
ulocimp_getParent(loc.data(), sink, &status);
loc = std::move(tmp);
} }
/* /*
char *i = uprv_strrchr(loc, '_'); char *i = uprv_strrchr(loc, '_');
@ -683,13 +669,13 @@ ucurr_getName(const char16_t* currency,
//|} //|}
if (U_FAILURE(*ec)) { if (U_FAILURE(*ec)) {
return 0; return nullptr;
} }
int32_t choice = (int32_t) nameStyle; int32_t choice = (int32_t) nameStyle;
if (choice < 0 || choice > 4) { if (choice < 0 || choice > 4) {
*ec = U_ILLEGAL_ARGUMENT_ERROR; *ec = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return nullptr;
} }
// In the future, resource bundles may implement multi-level // In the future, resource bundles may implement multi-level
@ -705,14 +691,10 @@ ucurr_getName(const char16_t* currency,
// this function. // this function.
UErrorCode ec2 = U_ZERO_ERROR; UErrorCode ec2 = U_ZERO_ERROR;
CharString loc; CharString loc = ulocimp_getName(locale, ec2);
{
CharStringByteSink sink(&loc);
ulocimp_getName(locale, sink, &ec2);
}
if (U_FAILURE(ec2)) { if (U_FAILURE(ec2)) {
*ec = U_ILLEGAL_ARGUMENT_ERROR; *ec = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return nullptr;
} }
char buf[ISO_CURRENCY_CODE_LENGTH+1]; char buf[ISO_CURRENCY_CODE_LENGTH+1];
@ -739,7 +721,7 @@ ucurr_getName(const char16_t* currency,
break; break;
default: default:
*ec = U_UNSUPPORTED_ERROR; *ec = U_UNSUPPORTED_ERROR;
return 0; return nullptr;
} }
key.append("/", ec2); key.append("/", ec2);
key.append(buf, ec2); key.append(buf, ec2);
@ -800,21 +782,17 @@ ucurr_getPluralName(const char16_t* currency,
//|} //|}
if (U_FAILURE(*ec)) { if (U_FAILURE(*ec)) {
return 0; return nullptr;
} }
// Use a separate UErrorCode here that does not propagate out of // Use a separate UErrorCode here that does not propagate out of
// this function. // this function.
UErrorCode ec2 = U_ZERO_ERROR; UErrorCode ec2 = U_ZERO_ERROR;
CharString loc; CharString loc = ulocimp_getName(locale, ec2);
{
CharStringByteSink sink(&loc);
ulocimp_getName(locale, sink, &ec2);
}
if (U_FAILURE(ec2)) { if (U_FAILURE(ec2)) {
*ec = U_ILLEGAL_ARGUMENT_ERROR; *ec = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return nullptr;
} }
char buf[ISO_CURRENCY_CODE_LENGTH+1]; char buf[ISO_CURRENCY_CODE_LENGTH+1];
@ -1002,11 +980,7 @@ collectCurrencyNames(const char* locale,
// Look up the Currencies resource for the given locale. // Look up the Currencies resource for the given locale.
UErrorCode ec2 = U_ZERO_ERROR; UErrorCode ec2 = U_ZERO_ERROR;
CharString loc; CharString loc = ulocimp_getName(locale, ec2);
{
CharStringByteSink sink(&loc);
ulocimp_getName(locale, sink, &ec2);
}
if (U_FAILURE(ec2)) { if (U_FAILURE(ec2)) {
ec = U_ILLEGAL_ARGUMENT_ERROR; ec = U_ILLEGAL_ARGUMENT_ERROR;
} }
@ -1390,7 +1364,6 @@ searchCurrencyName(const CurrencyNameStruct* currencyNames,
break; break;
} }
} }
return;
} }
//========================= currency name cache ===================== //========================= currency name cache =====================
@ -1447,7 +1420,7 @@ currency_cache_cleanup() {
for (int32_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) { for (int32_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
if (currCache[i]) { if (currCache[i]) {
deleteCacheEntry(currCache[i]); deleteCacheEntry(currCache[i]);
currCache[i] = 0; currCache[i] = nullptr;
} }
} }
return true; return true;
@ -2030,6 +2003,7 @@ static const struct CurrencyList {
{"XBC", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"XBC", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
{"XBD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"XBD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
{"XCD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"XCD", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"XCG", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"XDR", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"XDR", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
{"XEU", UCURR_UNCOMMON|UCURR_DEPRECATED}, {"XEU", UCURR_UNCOMMON|UCURR_DEPRECATED},
{"XFO", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"XFO", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
@ -2229,7 +2203,7 @@ static void U_CALLCONV initIsoCodes(UErrorCode &status) {
static void populateCurrSymbolsEquiv(icu::Hashtable *hash, UErrorCode &status) { static void populateCurrSymbolsEquiv(icu::Hashtable *hash, UErrorCode &status) {
if (U_FAILURE(status)) { return; } if (U_FAILURE(status)) { return; }
for (auto& entry : unisets::kCurrencyEntries) { for (const auto& entry : unisets::kCurrencyEntries) {
UnicodeString exemplar(entry.exemplar); UnicodeString exemplar(entry.exemplar);
const UnicodeSet* set = unisets::get(entry.key); const UnicodeSet* set = unisets::get(entry.key);
if (set == nullptr) { return; } if (set == nullptr) { return; }
@ -2325,10 +2299,9 @@ ucurr_countCurrencies(const char* locale,
{ {
// local variables // local variables
UErrorCode localStatus = U_ZERO_ERROR; UErrorCode localStatus = U_ZERO_ERROR;
char id[ULOC_FULLNAME_CAPACITY];
// get country or country_variant in `id' // get country or country_variant in `id'
idForLocale(locale, id, sizeof(id), ec); CharString id = idForLocale(locale, ec);
if (U_FAILURE(*ec)) if (U_FAILURE(*ec))
{ {
@ -2336,10 +2309,10 @@ ucurr_countCurrencies(const char* locale,
} }
// Remove variants, which is only needed for registration. // Remove variants, which is only needed for registration.
char *idDelim = strchr(id, VAR_DELIM); char *idDelim = strchr(id.data(), VAR_DELIM);
if (idDelim) if (idDelim)
{ {
idDelim[0] = 0; id.truncate(idDelim - id.data());
} }
// Look up the CurrencyMap element in the root bundle. // Look up the CurrencyMap element in the root bundle.
@ -2347,7 +2320,7 @@ ucurr_countCurrencies(const char* locale,
UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
// Using the id derived from the local, get the currency data // Using the id derived from the local, get the currency data
UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus);
// process each currency to see which one is valid for the given date // process each currency to see which one is valid for the given date
if (U_SUCCESS(localStatus)) if (U_SUCCESS(localStatus))
@ -2440,20 +2413,19 @@ ucurr_forLocaleAndDate(const char* locale,
{ {
// local variables // local variables
UErrorCode localStatus = U_ZERO_ERROR; UErrorCode localStatus = U_ZERO_ERROR;
char id[ULOC_FULLNAME_CAPACITY];
// get country or country_variant in `id' // get country or country_variant in `id'
idForLocale(locale, id, sizeof(id), ec); CharString id = idForLocale(locale, ec);
if (U_FAILURE(*ec)) if (U_FAILURE(*ec))
{ {
return 0; return 0;
} }
// Remove variants, which is only needed for registration. // Remove variants, which is only needed for registration.
char *idDelim = strchr(id, VAR_DELIM); char *idDelim = strchr(id.data(), VAR_DELIM);
if (idDelim) if (idDelim)
{ {
idDelim[0] = 0; id.truncate(idDelim - id.data());
} }
// Look up the CurrencyMap element in the root bundle. // Look up the CurrencyMap element in the root bundle.
@ -2461,7 +2433,7 @@ ucurr_forLocaleAndDate(const char* locale,
UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
// Using the id derived from the local, get the currency data // Using the id derived from the local, get the currency data
UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus);
// process each currency to see which one is valid for the given date // process each currency to see which one is valid for the given date
bool matchFound = false; bool matchFound = false;
@ -2587,8 +2559,7 @@ static const UEnumeration defaultKeywordValues = {
U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, const char *locale, UBool commonlyUsed, UErrorCode* status) { U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, const char *locale, UBool commonlyUsed, UErrorCode* status) {
// Resolve region // Resolve region
char prefRegion[ULOC_COUNTRY_CAPACITY]; CharString prefRegion = ulocimp_getRegionForSupplementalData(locale, true, *status);
ulocimp_getRegionForSupplementalData(locale, true, prefRegion, sizeof(prefRegion), status);
// Read value from supplementalData // Read value from supplementalData
UList *values = ulist_createEmptyList(status); UList *values = ulist_createEmptyList(status);
@ -2621,7 +2592,7 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key,
break; break;
} }
const char *region = ures_getKey(&bundlekey); const char *region = ures_getKey(&bundlekey);
UBool isPrefRegion = uprv_strcmp(region, prefRegion) == 0 ? true : false; UBool isPrefRegion = prefRegion == region;
if (!isPrefRegion && commonlyUsed) { if (!isPrefRegion && commonlyUsed) {
// With commonlyUsed=true, we do not put // With commonlyUsed=true, we do not put
// currencies for other regions in the // currencies for other regions in the
@ -2732,7 +2703,7 @@ ucurr_getNumericCode(const char16_t* currency) {
if (currency && u_strlen(currency) == ISO_CURRENCY_CODE_LENGTH) { if (currency && u_strlen(currency) == ISO_CURRENCY_CODE_LENGTH) {
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
UResourceBundle *bundle = ures_openDirect(0, "currencyNumericCodes", &status); UResourceBundle *bundle = ures_openDirect(nullptr, "currencyNumericCodes", &status);
ures_getByKey(bundle, "codeMap", bundle, &status); ures_getByKey(bundle, "codeMap", bundle, &status);
if (U_SUCCESS(status)) { if (U_SUCCESS(status)) {
char alphaCode[ISO_CURRENCY_CODE_LENGTH+1]; char alphaCode[ISO_CURRENCY_CODE_LENGTH+1];

View File

@ -850,8 +850,8 @@ static UBool extendICUData(UErrorCode *pErr)
UDataMemory_init(&copyPData); UDataMemory_init(&copyPData);
if(pData != nullptr) { if(pData != nullptr) {
UDatamemory_assign(&copyPData, pData); UDatamemory_assign(&copyPData, pData);
copyPData.map = 0; /* The mapping for this data is owned by the hash table */ copyPData.map = nullptr; /* The mapping for this data is owned by the hash table */
copyPData.mapAddr = 0; /* which will unmap it when ICU is shut down. */ copyPData.mapAddr = nullptr; /* which will unmap it when ICU is shut down. */
/* CommonICUData is also unmapped when ICU is shut down.*/ /* CommonICUData is also unmapped when ICU is shut down.*/
/* To avoid unmapping the data twice, zero out the map */ /* To avoid unmapping the data twice, zero out the map */
/* fields in the UDataMemory that we're assigning */ /* fields in the UDataMemory that we're assigning */

View File

@ -441,7 +441,7 @@ udata_openSwapperForInputData(const void *data, int32_t length,
pHeader->info.sizeofUChar!=2 pHeader->info.sizeofUChar!=2
) { ) {
*pErrorCode=U_UNSUPPORTED_ERROR; *pErrorCode=U_UNSUPPORTED_ERROR;
return 0; return nullptr;
} }
inIsBigEndian=(UBool)pHeader->info.isBigEndian; inIsBigEndian=(UBool)pHeader->info.isBigEndian;
@ -461,7 +461,7 @@ udata_openSwapperForInputData(const void *data, int32_t length,
(length>=0 && length<headerSize) (length>=0 && length<headerSize)
) { ) {
*pErrorCode=U_UNSUPPORTED_ERROR; *pErrorCode=U_UNSUPPORTED_ERROR;
return 0; return nullptr;
} }
return udata_openSwapper(inIsBigEndian, inCharset, outIsBigEndian, outCharset, pErrorCode); return udata_openSwapper(inIsBigEndian, inCharset, outIsBigEndian, outCharset, pErrorCode);

View File

@ -66,7 +66,7 @@ noopSetState(UCharIterator * /*iter*/, uint32_t /*state*/, UErrorCode *pErrorCod
} }
static const UCharIterator noopIterator={ static const UCharIterator noopIterator={
0, 0, 0, 0, 0, 0, nullptr, 0, 0, 0, 0, 0,
noopGetIndex, noopGetIndex,
noopMove, noopMove,
noopHasNext, noopHasNext,
@ -197,7 +197,7 @@ stringIteratorSetState(UCharIterator *iter, uint32_t state, UErrorCode *pErrorCo
} }
static const UCharIterator stringIterator={ static const UCharIterator stringIterator={
0, 0, 0, 0, 0, 0, nullptr, 0, 0, 0, 0, 0,
stringIteratorGetIndex, stringIteratorGetIndex,
stringIteratorMove, stringIteratorMove,
stringIteratorHasNext, stringIteratorHasNext,
@ -212,8 +212,8 @@ static const UCharIterator stringIterator={
U_CAPI void U_EXPORT2 U_CAPI void U_EXPORT2
uiter_setString(UCharIterator *iter, const char16_t *s, int32_t length) { uiter_setString(UCharIterator *iter, const char16_t *s, int32_t length) {
if(iter!=0) { if (iter != nullptr) {
if(s!=0 && length>=-1) { if (s != nullptr && length >= -1) {
*iter=stringIterator; *iter=stringIterator;
iter->context=s; iter->context=s;
if(length>=0) { if(length>=0) {
@ -283,7 +283,7 @@ utf16BEIteratorPrevious(UCharIterator *iter) {
} }
static const UCharIterator utf16BEIterator={ static const UCharIterator utf16BEIterator={
0, 0, 0, 0, 0, 0, nullptr, 0, 0, 0, 0, 0,
stringIteratorGetIndex, stringIteratorGetIndex,
stringIteratorMove, stringIteratorMove,
stringIteratorHasNext, stringIteratorHasNext,
@ -457,7 +457,7 @@ characterIteratorSetState(UCharIterator *iter, uint32_t state, UErrorCode *pErro
} }
static const UCharIterator characterIteratorWrapper={ static const UCharIterator characterIteratorWrapper={
0, 0, 0, 0, 0, 0, nullptr, 0, 0, 0, 0, 0,
characterIteratorGetIndex, characterIteratorGetIndex,
characterIteratorMove, characterIteratorMove,
characterIteratorHasNext, characterIteratorHasNext,
@ -472,8 +472,8 @@ static const UCharIterator characterIteratorWrapper={
U_CAPI void U_EXPORT2 U_CAPI void U_EXPORT2
uiter_setCharacterIterator(UCharIterator *iter, CharacterIterator *charIter) { uiter_setCharacterIterator(UCharIterator *iter, CharacterIterator *charIter) {
if(iter!=0) { if (iter != nullptr) {
if(charIter!=0) { if (charIter != nullptr) {
*iter=characterIteratorWrapper; *iter=characterIteratorWrapper;
iter->context=charIter; iter->context=charIter;
} else { } else {
@ -521,7 +521,7 @@ replaceableIteratorPrevious(UCharIterator *iter) {
} }
static const UCharIterator replaceableIterator={ static const UCharIterator replaceableIterator={
0, 0, 0, 0, 0, 0, nullptr, 0, 0, 0, 0, 0,
stringIteratorGetIndex, stringIteratorGetIndex,
stringIteratorMove, stringIteratorMove,
stringIteratorHasNext, stringIteratorHasNext,
@ -536,8 +536,8 @@ static const UCharIterator replaceableIterator={
U_CAPI void U_EXPORT2 U_CAPI void U_EXPORT2
uiter_setReplaceable(UCharIterator *iter, const Replaceable *rep) { uiter_setReplaceable(UCharIterator *iter, const Replaceable *rep) {
if(iter!=0) { if (iter != nullptr) {
if(rep!=0) { if (rep != nullptr) {
*iter=replaceableIterator; *iter=replaceableIterator;
iter->context=rep; iter->context=rep;
iter->limit=iter->length=rep->length(); iter->limit=iter->length=rep->length();
@ -987,7 +987,7 @@ utf8IteratorSetState(UCharIterator *iter,
} }
static const UCharIterator utf8Iterator={ static const UCharIterator utf8Iterator={
0, 0, 0, 0, 0, 0, nullptr, 0, 0, 0, 0, 0,
utf8IteratorGetIndex, utf8IteratorGetIndex,
utf8IteratorMove, utf8IteratorMove,
utf8IteratorHasNext, utf8IteratorHasNext,
@ -1002,8 +1002,8 @@ static const UCharIterator utf8Iterator={
U_CAPI void U_EXPORT2 U_CAPI void U_EXPORT2
uiter_setUTF8(UCharIterator *iter, const char *s, int32_t length) { uiter_setUTF8(UCharIterator *iter, const char *s, int32_t length) {
if(iter!=0) { if (iter != nullptr) {
if(s!=0 && length>=-1) { if (s != nullptr && length >= -1) {
*iter=utf8Iterator; *iter=utf8Iterator;
iter->context=s; iter->context=s;
if(length>=0) { if(length>=0) {

File diff suppressed because it is too large Load Diff

View File

@ -74,8 +74,9 @@ uloc_key_type_cleanup() {
U_CDECL_END U_CDECL_END
namespace {
static void U_CALLCONV void U_CALLCONV
initFromResourceBundle(UErrorCode& sts) { initFromResourceBundle(UErrorCode& sts) {
U_NAMESPACE_USE U_NAMESPACE_USE
ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KEY_TYPE, uloc_key_type_cleanup); ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KEY_TYPE, uloc_key_type_cleanup);
@ -141,7 +142,7 @@ initFromResourceBundle(UErrorCode& sts) {
bcpKeyId = bcpKeyIdBuf->data(); bcpKeyId = bcpKeyIdBuf->data();
} }
UBool isTZ = uprv_strcmp(legacyKeyId, "timezone") == 0; bool isTZ = uprv_strcmp(legacyKeyId, "timezone") == 0;
UHashtable* typeDataMap = uhash_open(uhash_hashIChars, uhash_compareIChars, nullptr, &sts); UHashtable* typeDataMap = uhash_open(uhash_hashIChars, uhash_compareIChars, nullptr, &sts);
if (U_FAILURE(sts)) { if (U_FAILURE(sts)) {
@ -351,7 +352,7 @@ initFromResourceBundle(UErrorCode& sts) {
} }
} }
static UBool bool
init() { init() {
UErrorCode sts = U_ZERO_ERROR; UErrorCode sts = U_ZERO_ERROR;
umtx_initOnce(gLocExtKeyMapInitOnce, &initFromResourceBundle, sts); umtx_initOnce(gLocExtKeyMapInitOnce, &initFromResourceBundle, sts);
@ -361,7 +362,7 @@ init() {
return true; return true;
} }
static UBool bool
isSpecialTypeCodepoints(const char* val) { isSpecialTypeCodepoints(const char* val) {
int32_t subtagLen = 0; int32_t subtagLen = 0;
const char* p = val; const char* p = val;
@ -383,7 +384,7 @@ isSpecialTypeCodepoints(const char* val) {
return (subtagLen >= 4 && subtagLen <= 6); return (subtagLen >= 4 && subtagLen <= 6);
} }
static UBool bool
isSpecialTypeReorderCode(const char* val) { isSpecialTypeReorderCode(const char* val) {
int32_t subtagLen = 0; int32_t subtagLen = 0;
const char* p = val; const char* p = val;
@ -403,7 +404,7 @@ isSpecialTypeReorderCode(const char* val) {
return (subtagLen >=3 && subtagLen <=8); return (subtagLen >=3 && subtagLen <=8);
} }
static UBool bool
isSpecialTypeRgKeyValue(const char* val) { isSpecialTypeRgKeyValue(const char* val) {
int32_t subtagLen = 0; int32_t subtagLen = 0;
const char* p = val; const char* p = val;
@ -419,7 +420,9 @@ isSpecialTypeRgKeyValue(const char* val) {
return (subtagLen == 6); return (subtagLen == 6);
} }
U_CFUNC const char* } // namespace
U_EXPORT const char*
ulocimp_toBcpKey(const char* key) { ulocimp_toBcpKey(const char* key) {
if (!init()) { if (!init()) {
return nullptr; return nullptr;
@ -432,7 +435,7 @@ ulocimp_toBcpKey(const char* key) {
return nullptr; return nullptr;
} }
U_CFUNC const char* U_EXPORT const char*
ulocimp_toLegacyKey(const char* key) { ulocimp_toLegacyKey(const char* key) {
if (!init()) { if (!init()) {
return nullptr; return nullptr;
@ -445,8 +448,8 @@ ulocimp_toLegacyKey(const char* key) {
return nullptr; return nullptr;
} }
U_CFUNC const char* U_EXPORT const char*
ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType) { ulocimp_toBcpType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType) {
if (isKnownKey != nullptr) { if (isKnownKey != nullptr) {
*isKnownKey = false; *isKnownKey = false;
} }
@ -468,7 +471,7 @@ ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* i
return t->bcpId; return t->bcpId;
} }
if (keyData->specialTypes != SPECIALTYPE_NONE) { if (keyData->specialTypes != SPECIALTYPE_NONE) {
UBool matched = false; bool matched = false;
if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) { if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) {
matched = isSpecialTypeCodepoints(type); matched = isSpecialTypeCodepoints(type);
} }
@ -490,8 +493,8 @@ ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* i
} }
U_CFUNC const char* U_EXPORT const char*
ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType) { ulocimp_toLegacyType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType) {
if (isKnownKey != nullptr) { if (isKnownKey != nullptr) {
*isKnownKey = false; *isKnownKey = false;
} }
@ -513,7 +516,7 @@ ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool
return t->legacyId; return t->legacyId;
} }
if (keyData->specialTypes != SPECIALTYPE_NONE) { if (keyData->specialTypes != SPECIALTYPE_NONE) {
UBool matched = false; bool matched = false;
if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) { if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) {
matched = isSpecialTypeCodepoints(type); matched = isSpecialTypeCodepoints(type);
} }
@ -533,4 +536,3 @@ ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool
} }
return nullptr; return nullptr;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
// © 2023 and later: Unicode, Inc. and others. // © 2023 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html // License & terms of use: http://www.unicode.org/copyright.html
// //
#include "unicode/bytestream.h"
#include "unicode/errorcode.h" #include "unicode/errorcode.h"
#include "unicode/stringpiece.h" #include "unicode/stringpiece.h"
#include "unicode/utypes.h" #include "unicode/utypes.h"
@ -8,9 +9,9 @@
#include "unicode/ulocale.h" #include "unicode/ulocale.h"
#include "unicode/locid.h" #include "unicode/locid.h"
#include "bytesinkutil.h"
#include "charstr.h" #include "charstr.h"
#include "cmemory.h" #include "cmemory.h"
#include "ustr_imp.h"
U_NAMESPACE_USE U_NAMESPACE_USE
#define EXTERNAL(i) (reinterpret_cast<ULocale*>(i)) #define EXTERNAL(i) (reinterpret_cast<ULocale*>(i))
@ -19,15 +20,17 @@ U_NAMESPACE_USE
ULocale* ULocale*
ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err) { ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err) {
if (U_FAILURE(*err)) { return nullptr; }
CharString str(length < 0 ? StringPiece(localeID) : StringPiece(localeID, length), *err); CharString str(length < 0 ? StringPiece(localeID) : StringPiece(localeID, length), *err);
if (U_FAILURE(*err)) return nullptr; if (U_FAILURE(*err)) { return nullptr; }
return EXTERNAL(icu::Locale::createFromName(str.data()).clone()); return EXTERNAL(icu::Locale::createFromName(str.data()).clone());
} }
ULocale* ULocale*
ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err) { ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err) {
if (U_FAILURE(*err)) { return nullptr; }
Locale l = icu::Locale::forLanguageTag(length < 0 ? StringPiece(tag) : StringPiece(tag, length), *err); Locale l = icu::Locale::forLanguageTag(length < 0 ? StringPiece(tag) : StringPiece(tag, length), *err);
if (U_FAILURE(*err)) return nullptr; if (U_FAILURE(*err)) { return nullptr; }
return EXTERNAL(l.clone()); return EXTERNAL(l.clone());
} }
@ -53,20 +56,14 @@ int32_t ulocale_get ##N ( \
*err = U_ILLEGAL_ARGUMENT_ERROR; \ *err = U_ILLEGAL_ARGUMENT_ERROR; \
return 0; \ return 0; \
} \ } \
CheckedArrayByteSink sink(valueBuffer, bufferCapacity); \ return ByteSinkUtil::viaByteSinkToTerminatedChars( \
valueBuffer, bufferCapacity, \
[&](ByteSink& sink, UErrorCode& status) { \
CONST_INTERNAL(locale)->get ## N( \ CONST_INTERNAL(locale)->get ## N( \
keywordLength < 0 ? StringPiece(keyword) : StringPiece(keyword, keywordLength), \ keywordLength < 0 ? StringPiece(keyword) : StringPiece(keyword, keywordLength), \
sink, *err); \ sink, status); \
int32_t reslen = sink.NumberOfBytesAppended(); \ }, \
if (U_FAILURE(*err)) { \ *err); \
return reslen; \
} \
if (sink.Overflowed()) { \
*err = U_BUFFER_OVERFLOW_ERROR; \
} else { \
u_terminateChars(valueBuffer, bufferCapacity, reslen, err); \
} \
return reslen; \
} }
#define IMPL_ULOCALE_GET_KEYWORDS(N) \ #define IMPL_ULOCALE_GET_KEYWORDS(N) \

View File

@ -9,10 +9,10 @@
#include "unicode/stringpiece.h" #include "unicode/stringpiece.h"
#include "unicode/umachine.h" #include "unicode/umachine.h"
#include "unicode/ulocbuilder.h" #include "unicode/ulocbuilder.h"
#include "bytesinkutil.h"
#include "cstring.h" #include "cstring.h"
#include "ustr_imp.h" #include "ustr_imp.h"
using icu::CheckedArrayByteSink;
using icu::StringPiece; using icu::StringPiece;
#define EXTERNAL(i) (reinterpret_cast<ULocaleBuilder*>(i)) #define EXTERNAL(i) (reinterpret_cast<ULocaleBuilder*>(i))
@ -112,12 +112,13 @@ ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err) {
int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder, int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder,
char* buffer, int32_t bufferCapacity, UErrorCode* err) { char* buffer, int32_t bufferCapacity, UErrorCode* err) {
if (U_FAILURE(*err)) { return 0; }
if (builder == nullptr) { if (builder == nullptr) {
*err = U_ILLEGAL_ARGUMENT_ERROR; *err = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return 0;
} }
icu::Locale l = INTERNAL(builder)->build(*err); icu::Locale l = INTERNAL(builder)->build(*err);
if (U_FAILURE(*err)) return 0; if (U_FAILURE(*err)) { return 0; }
int32_t length = (int32_t)(uprv_strlen(l.getName())); int32_t length = (int32_t)(uprv_strlen(l.getName()));
if (0 < length && length <= bufferCapacity) { if (0 < length && length <= bufferCapacity) {
uprv_memcpy(buffer, l.getName(), length); uprv_memcpy(buffer, l.getName(), length);
@ -127,24 +128,18 @@ int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder,
int32_t ulocbld_buildLanguageTag(ULocaleBuilder* builder, int32_t ulocbld_buildLanguageTag(ULocaleBuilder* builder,
char* buffer, int32_t bufferCapacity, UErrorCode* err) { char* buffer, int32_t bufferCapacity, UErrorCode* err) {
if (U_FAILURE(*err)) { return 0; }
if (builder == nullptr) { if (builder == nullptr) {
*err = U_ILLEGAL_ARGUMENT_ERROR; *err = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return 0;
} }
icu::Locale l = INTERNAL(builder)->build(*err); icu::Locale l = INTERNAL(builder)->build(*err);
if (U_FAILURE(*err)) return 0; return icu::ByteSinkUtil::viaByteSinkToTerminatedChars(
CheckedArrayByteSink sink(buffer, bufferCapacity); buffer, bufferCapacity,
l.toLanguageTag(sink, *err); [&](icu::ByteSink& sink, UErrorCode& status) {
int32_t reslen = sink.NumberOfBytesAppended(); l.toLanguageTag(sink, status);
if (U_FAILURE(*err)) { },
return reslen; *err);
}
if (sink.Overflowed()) {
*err = U_BUFFER_OVERFLOW_ERROR;
} else {
u_terminateChars(buffer, bufferCapacity, reslen, err);
}
return reslen;
} }
UBool ulocbld_copyErrorTo(const ULocaleBuilder* builder, UErrorCode *outErrorCode) { UBool ulocbld_copyErrorTo(const ULocaleBuilder* builder, UErrorCode *outErrorCode) {

View File

@ -10,6 +10,8 @@
#ifndef ULOCIMP_H #ifndef ULOCIMP_H
#define ULOCIMP_H #define ULOCIMP_H
#include <cstddef>
#include "unicode/bytestream.h" #include "unicode/bytestream.h"
#include "unicode/uloc.h" #include "unicode/uloc.h"
@ -40,8 +42,10 @@ uloc_getTableStringWithFallback(
int32_t *pLength, int32_t *pLength,
UErrorCode *pErrorCode); UErrorCode *pErrorCode);
namespace {
/*returns true if a is an ID separator false otherwise*/ /*returns true if a is an ID separator false otherwise*/
#define _isIDSeparator(a) (a == '_' || a == '-') inline bool _isIDSeparator(char a) { return a == '_' || a == '-'; }
} // namespace
U_CFUNC const char* U_CFUNC const char*
uloc_getCurrentCountryID(const char* oldID); uloc_getCurrentCountryID(const char* oldID);
@ -49,53 +53,134 @@ uloc_getCurrentCountryID(const char* oldID);
U_CFUNC const char* U_CFUNC const char*
uloc_getCurrentLanguageID(const char* oldID); uloc_getCurrentLanguageID(const char* oldID);
U_CFUNC void U_EXPORT icu::CharString
ulocimp_getKeywords(const char *localeID, ulocimp_getKeywords(const char* localeID,
char prev,
bool valuesToo,
UErrorCode& status);
U_EXPORT void
ulocimp_getKeywords(const char* localeID,
char prev, char prev,
icu::ByteSink& sink, icu::ByteSink& sink,
UBool valuesToo, bool valuesToo,
UErrorCode *status); UErrorCode& status);
icu::CharString U_EXPORT2 U_EXPORT icu::CharString
ulocimp_getLanguage(const char *localeID, ulocimp_getName(const char* localeID,
const char **pEnd, UErrorCode& err);
UErrorCode &status);
icu::CharString U_EXPORT2 U_EXPORT void
ulocimp_getScript(const char *localeID,
const char **pEnd,
UErrorCode &status);
icu::CharString U_EXPORT2
ulocimp_getCountry(const char *localeID,
const char **pEnd,
UErrorCode &status);
U_CAPI void U_EXPORT2
ulocimp_getName(const char* localeID, ulocimp_getName(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* err); UErrorCode& err);
U_CAPI void U_EXPORT2 U_EXPORT icu::CharString
ulocimp_getBaseName(const char* localeID,
UErrorCode& err);
U_EXPORT void
ulocimp_getBaseName(const char* localeID, ulocimp_getBaseName(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* err); UErrorCode& err);
U_CAPI void U_EXPORT2 U_EXPORT icu::CharString
ulocimp_canonicalize(const char* localeID,
UErrorCode& err);
U_EXPORT void
ulocimp_canonicalize(const char* localeID, ulocimp_canonicalize(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* err); UErrorCode& err);
U_CAPI void U_EXPORT2 U_EXPORT icu::CharString
ulocimp_getKeywordValue(const char* localeID,
const char* keywordName,
UErrorCode& status);
U_EXPORT void
ulocimp_getKeywordValue(const char* localeID, ulocimp_getKeywordValue(const char* localeID,
const char* keywordName, const char* keywordName,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* status); UErrorCode& status);
U_CAPI void U_EXPORT2 U_EXPORT icu::CharString
ulocimp_getLanguage(const char* localeID, UErrorCode& status);
U_EXPORT icu::CharString
ulocimp_getScript(const char* localeID, UErrorCode& status);
U_EXPORT icu::CharString
ulocimp_getRegion(const char* localeID, UErrorCode& status);
U_EXPORT icu::CharString
ulocimp_getVariant(const char* localeID, UErrorCode& status);
U_EXPORT void
ulocimp_setKeywordValue(const char* keywordName,
const char* keywordValue,
icu::CharString& localeID,
UErrorCode& status);
U_EXPORT int32_t
ulocimp_setKeywordValue(const char* keywords,
const char* keywordName,
const char* keywordValue,
icu::ByteSink& sink,
UErrorCode& status);
U_EXPORT void
ulocimp_getSubtags(
const char* localeID,
icu::CharString* language,
icu::CharString* script,
icu::CharString* region,
icu::CharString* variant,
const char** pEnd,
UErrorCode& status);
U_EXPORT void
ulocimp_getSubtags(
const char* localeID,
icu::ByteSink* language,
icu::ByteSink* script,
icu::ByteSink* region,
icu::ByteSink* variant,
const char** pEnd,
UErrorCode& status);
inline void
ulocimp_getSubtags(
const char* localeID,
std::nullptr_t,
std::nullptr_t,
std::nullptr_t,
std::nullptr_t,
const char** pEnd,
UErrorCode& status) {
ulocimp_getSubtags(
localeID,
static_cast<icu::ByteSink*>(nullptr),
static_cast<icu::ByteSink*>(nullptr),
static_cast<icu::ByteSink*>(nullptr),
static_cast<icu::ByteSink*>(nullptr),
pEnd,
status);
}
U_EXPORT icu::CharString
ulocimp_getParent(const char* localeID,
UErrorCode& err);
U_EXPORT void
ulocimp_getParent(const char* localeID, ulocimp_getParent(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* err); UErrorCode& err);
U_EXPORT icu::CharString
ulocimp_toLanguageTag(const char* localeID,
bool strict,
UErrorCode& status);
/** /**
* Writes a well-formed language tag for this locale ID. * Writes a well-formed language tag for this locale ID.
@ -116,11 +201,17 @@ ulocimp_getParent(const char* localeID,
* *
* @internal ICU 64 * @internal ICU 64
*/ */
U_CAPI void U_EXPORT2 U_EXPORT void
ulocimp_toLanguageTag(const char* localeID, ulocimp_toLanguageTag(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
UBool strict, bool strict,
UErrorCode* err); UErrorCode& err);
U_EXPORT icu::CharString
ulocimp_forLanguageTag(const char* langtag,
int32_t tagLen,
int32_t* parsedLength,
UErrorCode& status);
/** /**
* Returns a locale ID for the specified BCP47 language tag string. * Returns a locale ID for the specified BCP47 language tag string.
@ -148,12 +239,12 @@ ulocimp_toLanguageTag(const char* localeID,
* failed. * failed.
* @internal ICU 63 * @internal ICU 63
*/ */
U_CAPI void U_EXPORT2 U_EXPORT void
ulocimp_forLanguageTag(const char* langtag, ulocimp_forLanguageTag(const char* langtag,
int32_t tagLen, int32_t tagLen,
icu::ByteSink& sink, icu::ByteSink& sink,
int32_t* parsedLength, int32_t* parsedLength,
UErrorCode* err); UErrorCode& err);
/** /**
* Get the region to use for supplemental data lookup. Uses * Get the region to use for supplemental data lookup. Uses
@ -161,7 +252,7 @@ ulocimp_forLanguageTag(const char* langtag,
* (2) any unicode_region_tag in the locale ID; if none then * (2) any unicode_region_tag in the locale ID; if none then
* (3) if inferRegion is true, the region suggested by * (3) if inferRegion is true, the region suggested by
* getLikelySubtags on the localeID. * getLikelySubtags on the localeID.
* If no region is found, returns length 0. * If no region is found, returns an empty string.
* *
* @param localeID * @param localeID
* The complete locale ID (with keywords) from which * The complete locale ID (with keywords) from which
@ -169,20 +260,19 @@ ulocimp_forLanguageTag(const char* langtag,
* @param inferRegion * @param inferRegion
* If true, will try to infer region from localeID if * If true, will try to infer region from localeID if
* no other region is found. * no other region is found.
* @param region
* Buffer in which to put the region ID found; should
* have a capacity at least ULOC_COUNTRY_CAPACITY.
* @param regionCapacity
* The actual capacity of the region buffer.
* @param status * @param status
* Pointer to in/out UErrorCode value for latest status. * Pointer to in/out UErrorCode value for latest status.
* @return * @return
* The length of any region code found, or 0 if none. * The region code found, empty if none found.
* @internal ICU 57 * @internal ICU 57
*/ */
U_CAPI int32_t U_EXPORT2 U_EXPORT icu::CharString
ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion, ulocimp_getRegionForSupplementalData(const char *localeID, bool inferRegion,
char *region, int32_t regionCapacity, UErrorCode* status); UErrorCode& status);
U_EXPORT icu::CharString
ulocimp_addLikelySubtags(const char* localeID,
UErrorCode& status);
/** /**
* Add the likely subtags for a provided locale ID, per the algorithm described * Add the likely subtags for a provided locale ID, per the algorithm described
@ -213,10 +303,15 @@ ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
* or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR. * or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR.
* @internal ICU 64 * @internal ICU 64
*/ */
U_CAPI void U_EXPORT2 U_EXPORT void
ulocimp_addLikelySubtags(const char* localeID, ulocimp_addLikelySubtags(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
UErrorCode* err); UErrorCode& err);
U_EXPORT icu::CharString
ulocimp_minimizeSubtags(const char* localeID,
bool favorScript,
UErrorCode& status);
/** /**
* Minimize the subtags for a provided locale ID, per the algorithm described * Minimize the subtags for a provided locale ID, per the algorithm described
@ -248,70 +343,72 @@ ulocimp_addLikelySubtags(const char* localeID,
* or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR. * or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR.
* @internal ICU 64 * @internal ICU 64
*/ */
U_CAPI void U_EXPORT2 U_EXPORT void
ulocimp_minimizeSubtags(const char* localeID, ulocimp_minimizeSubtags(const char* localeID,
icu::ByteSink& sink, icu::ByteSink& sink,
bool favorScript, bool favorScript,
UErrorCode* err); UErrorCode& err);
U_CAPI const char * U_EXPORT2 U_CAPI const char * U_EXPORT2
locale_getKeywordsStart(const char *localeID); locale_getKeywordsStart(const char *localeID);
U_CFUNC UBool bool
ultag_isExtensionSubtags(const char* s, int32_t len); ultag_isExtensionSubtags(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isLanguageSubtag(const char* s, int32_t len); ultag_isLanguageSubtag(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isPrivateuseValueSubtags(const char* s, int32_t len); ultag_isPrivateuseValueSubtags(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isRegionSubtag(const char* s, int32_t len); ultag_isRegionSubtag(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isScriptSubtag(const char* s, int32_t len); ultag_isScriptSubtag(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isTransformedExtensionSubtags(const char* s, int32_t len); ultag_isTransformedExtensionSubtags(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isUnicodeExtensionSubtags(const char* s, int32_t len); ultag_isUnicodeExtensionSubtags(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isUnicodeLocaleAttribute(const char* s, int32_t len); ultag_isUnicodeLocaleAttribute(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isUnicodeLocaleAttributes(const char* s, int32_t len); ultag_isUnicodeLocaleAttributes(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isUnicodeLocaleKey(const char* s, int32_t len); ultag_isUnicodeLocaleKey(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isUnicodeLocaleType(const char* s, int32_t len); ultag_isUnicodeLocaleType(const char* s, int32_t len);
U_CFUNC UBool bool
ultag_isVariantSubtags(const char* s, int32_t len); ultag_isVariantSubtags(const char* s, int32_t len);
U_CAPI const char * U_EXPORT2 const char*
ultag_getTKeyStart(const char *localeID); ultag_getTKeyStart(const char* localeID);
U_CFUNC const char* U_EXPORT const char*
ulocimp_toBcpKey(const char* key); ulocimp_toBcpKey(const char* key);
U_CFUNC const char* U_EXPORT const char*
ulocimp_toLegacyKey(const char* key); ulocimp_toLegacyKey(const char* key);
U_CFUNC const char* U_EXPORT const char*
ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType); ulocimp_toBcpType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType);
U_CFUNC const char* U_EXPORT const char*
ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType); ulocimp_toLegacyType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType);
/* Function for testing purpose */ /* Function for testing purpose */
U_CAPI const char* const* ulocimp_getKnownCanonicalizedLocaleForTest(int32_t* length); U_EXPORT const char* const*
ulocimp_getKnownCanonicalizedLocaleForTest(int32_t& length);
// Return true if the value is already canonicalized. // Return true if the value is already canonicalized.
U_CAPI bool ulocimp_isCanonicalizedLocaleForTest(const char* localeName); U_EXPORT bool
ulocimp_isCanonicalizedLocaleForTest(const char* localeName);
#endif #endif

View File

@ -236,9 +236,9 @@ typedef HANDLE MemoryMap;
/* get a view of the mapping */ /* get a view of the mapping */
#if U_PLATFORM != U_PF_HPUX #if U_PLATFORM != U_PF_HPUX
data=mmap(0, length, PROT_READ, MAP_SHARED, fd, 0); data=mmap(nullptr, length, PROT_READ, MAP_SHARED, fd, 0);
#else #else
data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0); data=mmap(nullptr, length, PROT_READ, MAP_PRIVATE, fd, 0);
#endif #endif
close(fd); /* no longer needed */ close(fd); /* no longer needed */
if(data==MAP_FAILED) { if(data==MAP_FAILED) {
@ -262,7 +262,7 @@ typedef HANDLE MemoryMap;
if(munmap(pData->mapAddr, dataLen)==-1) { if(munmap(pData->mapAddr, dataLen)==-1) {
} }
pData->pHeader=nullptr; pData->pHeader=nullptr;
pData->map=0; pData->map=nullptr;
pData->mapAddr=nullptr; pData->mapAddr=nullptr;
} }
} }

View File

@ -189,7 +189,6 @@ u_setMutexFunctions(const void * /*context */, UMtxInitFn *, UMtxFn *,
if (U_SUCCESS(*status)) { if (U_SUCCESS(*status)) {
*status = U_UNSUPPORTED_ERROR; *status = U_UNSUPPORTED_ERROR;
} }
return;
} }
@ -200,5 +199,4 @@ u_setAtomicIncDecFunctions(const void * /*context */, UMtxAtomicFn *, UMtxAtomic
if (U_SUCCESS(*status)) { if (U_SUCCESS(*status)) {
*status = U_UNSUPPORTED_ERROR; *status = U_UNSUPPORTED_ERROR;
} }
return;
} }

View File

@ -146,14 +146,13 @@ public:
* will return distinct unequal values. * will return distinct unequal values.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UClassID getDynamicClassID(void) const override = 0; virtual UClassID getDynamicClassID() const override = 0;
/** /**
* Return a CharacterIterator over the text being analyzed. * Return a CharacterIterator over the text being analyzed.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual CharacterIterator& getText(void) const = 0; virtual CharacterIterator& getText() const = 0;
/** /**
* Get a UText for the text being analyzed. * Get a UText for the text being analyzed.
@ -228,14 +227,14 @@ public:
* @return The offset of the beginning of the text, zero. * @return The offset of the beginning of the text, zero.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t first(void) = 0; virtual int32_t first() = 0;
/** /**
* Set the iterator position to the index immediately BEYOND the last character in the text being scanned. * Set the iterator position to the index immediately BEYOND the last character in the text being scanned.
* @return The index immediately BEYOND the last character in the text being scanned. * @return The index immediately BEYOND the last character in the text being scanned.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t last(void) = 0; virtual int32_t last() = 0;
/** /**
* Set the iterator position to the boundary preceding the current boundary. * Set the iterator position to the boundary preceding the current boundary.
@ -243,7 +242,7 @@ public:
* boundaries have been returned. * boundaries have been returned.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t previous(void) = 0; virtual int32_t previous() = 0;
/** /**
* Advance the iterator to the boundary following the current boundary. * Advance the iterator to the boundary following the current boundary.
@ -251,14 +250,14 @@ public:
* boundaries have been returned. * boundaries have been returned.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t next(void) = 0; virtual int32_t next() = 0;
/** /**
* Return character index of the current iterator position within the text. * Return character index of the current iterator position within the text.
* @return The boundary most recently returned. * @return The boundary most recently returned.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t current(void) const = 0; virtual int32_t current() const = 0;
/** /**
* Advance the iterator to the first boundary following the specified offset. * Advance the iterator to the first boundary following the specified offset.
@ -530,7 +529,7 @@ public:
* must be closed by an explicit call to the destructor (not delete). * must be closed by an explicit call to the destructor (not delete).
* @deprecated ICU 52. Always delete the BreakIterator. * @deprecated ICU 52. Always delete the BreakIterator.
*/ */
inline UBool isBufferClone(void); inline UBool isBufferClone();
#endif /* U_HIDE_DEPRECATED_API */ #endif /* U_HIDE_DEPRECATED_API */
@ -575,7 +574,7 @@ public:
* @return a StringEnumeration over the locales available at the time of the call * @return a StringEnumeration over the locales available at the time of the call
* @stable ICU 2.4 * @stable ICU 2.4
*/ */
static StringEnumeration* U_EXPORT2 getAvailableLocales(void); static StringEnumeration* U_EXPORT2 getAvailableLocales();
#endif #endif
/** /**

View File

@ -128,9 +128,10 @@ public:
* @param skipZeros determine if skip zeros * @param skipZeros determine if skip zeros
* @param result the results in a set. * @param result the results in a set.
* @param status Fill-in parameter which receives the status of this operation. * @param status Fill-in parameter which receives the status of this operation.
* @param depth depth of the call.
* @internal * @internal
*/ */
static void U_EXPORT2 permute(UnicodeString &source, UBool skipZeros, Hashtable *result, UErrorCode &status); static void U_EXPORT2 permute(UnicodeString &source, UBool skipZeros, Hashtable *result, UErrorCode &status, int32_t depth=0);
#endif /* U_HIDE_INTERNAL_API */ #endif /* U_HIDE_INTERNAL_API */
/** /**
@ -182,8 +183,8 @@ private:
// transient fields // transient fields
UnicodeString buffer; UnicodeString buffer;
const Normalizer2 &nfd; const Normalizer2 *nfd;
const Normalizer2Impl &nfcImpl; const Normalizer2Impl *nfcImpl;
// we have a segment, in NFD. Find all the strings that are canonically equivalent to it. // we have a segment, in NFD. Find all the strings that are canonically equivalent to it.
UnicodeString *getEquivalents(const UnicodeString &segment, int32_t &result_len, UErrorCode &status); //private String[] getEquivalents(String segment) UnicodeString *getEquivalents(const UnicodeString &segment, int32_t &result_len, UErrorCode &status); //private String[] getEquivalents(String segment)

View File

@ -133,7 +133,7 @@ public:
* @return the hash code. * @return the hash code.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t hashCode(void) const = 0; virtual int32_t hashCode() const = 0;
/** /**
* Returns a UClassID for this ForwardCharacterIterator ("poor man's * Returns a UClassID for this ForwardCharacterIterator ("poor man's
@ -142,7 +142,7 @@ public:
* @return a UClassID for this ForwardCharacterIterator * @return a UClassID for this ForwardCharacterIterator
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UClassID getDynamicClassID(void) const override = 0; virtual UClassID getDynamicClassID() const override = 0;
/** /**
* Gets the current code unit for returning and advances to the next code unit * Gets the current code unit for returning and advances to the next code unit
@ -152,7 +152,7 @@ public:
* @return the current code unit. * @return the current code unit.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t nextPostInc(void) = 0; virtual char16_t nextPostInc() = 0;
/** /**
* Gets the current code point for returning and advances to the next code point * Gets the current code point for returning and advances to the next code point
@ -162,7 +162,7 @@ public:
* @return the current code point. * @return the current code point.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 next32PostInc(void) = 0; virtual UChar32 next32PostInc() = 0;
/** /**
* Returns false if there are no more code units or code points * Returns false if there are no more code units or code points
@ -389,7 +389,7 @@ public:
* @return the first code unit in its iteration range. * @return the first code unit in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t first(void) = 0; virtual char16_t first() = 0;
/** /**
* Sets the iterator to refer to the first code unit in its * Sets the iterator to refer to the first code unit in its
@ -399,7 +399,7 @@ public:
* @return the first code unit in its iteration range. * @return the first code unit in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t firstPostInc(void); virtual char16_t firstPostInc();
/** /**
* Sets the iterator to refer to the first code point in its * Sets the iterator to refer to the first code point in its
@ -410,7 +410,7 @@ public:
* @return the first code point in its iteration range. * @return the first code point in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 first32(void) = 0; virtual UChar32 first32() = 0;
/** /**
* Sets the iterator to refer to the first code point in its * Sets the iterator to refer to the first code point in its
@ -420,7 +420,7 @@ public:
* @return the first code point in its iteration range. * @return the first code point in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 first32PostInc(void); virtual UChar32 first32PostInc();
/** /**
* Sets the iterator to refer to the first code unit or code point in its * Sets the iterator to refer to the first code unit or code point in its
@ -438,7 +438,7 @@ public:
* @return the last code unit. * @return the last code unit.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t last(void) = 0; virtual char16_t last() = 0;
/** /**
* Sets the iterator to refer to the last code point in its * Sets the iterator to refer to the last code point in its
@ -447,7 +447,7 @@ public:
* @return the last code point. * @return the last code point.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 last32(void) = 0; virtual UChar32 last32() = 0;
/** /**
* Sets the iterator to the end of its iteration range, just behind * Sets the iterator to the end of its iteration range, just behind
@ -486,14 +486,14 @@ public:
* @return the current code unit. * @return the current code unit.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t current(void) const = 0; virtual char16_t current() const = 0;
/** /**
* Returns the code point the iterator currently refers to. * Returns the code point the iterator currently refers to.
* @return the current code point. * @return the current code point.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 current32(void) const = 0; virtual UChar32 current32() const = 0;
/** /**
* Advances to the next code unit in the iteration range * Advances to the next code unit in the iteration range
@ -502,7 +502,7 @@ public:
* @return the next code unit. * @return the next code unit.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t next(void) = 0; virtual char16_t next() = 0;
/** /**
* Advances to the next code point in the iteration range * Advances to the next code point in the iteration range
@ -514,7 +514,7 @@ public:
* @return the next code point. * @return the next code point.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 next32(void) = 0; virtual UChar32 next32() = 0;
/** /**
* Advances to the previous code unit in the iteration range * Advances to the previous code unit in the iteration range
@ -523,7 +523,7 @@ public:
* @return the previous code unit. * @return the previous code unit.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t previous(void) = 0; virtual char16_t previous() = 0;
/** /**
* Advances to the previous code point in the iteration range * Advances to the previous code point in the iteration range
@ -532,7 +532,7 @@ public:
* @return the previous code point. * @return the previous code point.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 previous32(void) = 0; virtual UChar32 previous32() = 0;
/** /**
* Returns false if there are no more code units or code points * Returns false if there are no more code units or code points
@ -555,7 +555,7 @@ public:
* object of the character returned by first(). * object of the character returned by first().
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t startIndex(void) const; inline int32_t startIndex() const;
/** /**
* Returns the numeric index in the underlying text-storage * Returns the numeric index in the underlying text-storage
@ -566,7 +566,7 @@ public:
* returned by last(). * returned by last().
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t endIndex(void) const; inline int32_t endIndex() const;
/** /**
* Returns the numeric index in the underlying text-storage * Returns the numeric index in the underlying text-storage
@ -576,7 +576,7 @@ public:
* the character the iterator currently refers to * the character the iterator currently refers to
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t getIndex(void) const; inline int32_t getIndex() const;
/** /**
* Returns the length of the entire text in the underlying * Returns the length of the entire text in the underlying
@ -708,22 +708,22 @@ CharacterIterator::setToEnd() {
} }
inline int32_t inline int32_t
CharacterIterator::startIndex(void) const { CharacterIterator::startIndex() const {
return begin; return begin;
} }
inline int32_t inline int32_t
CharacterIterator::endIndex(void) const { CharacterIterator::endIndex() const {
return end; return end;
} }
inline int32_t inline int32_t
CharacterIterator::getIndex(void) const { CharacterIterator::getIndex() const {
return pos; return pos;
} }
inline int32_t inline int32_t
CharacterIterator::getLength(void) const { CharacterIterator::getLength() const {
return textLength; return textLength;
} }

View File

@ -143,6 +143,11 @@
* <td>icu::MessageFormat</td> * <td>icu::MessageFormat</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>Message Formatting 2<br/>(technology preview)</td>
* <td>(no C API)</td>
* <td>icu::message2::MessageFormatter</td>
* </tr>
* <tr>
* <td>List Formatting</td> * <td>List Formatting</td>
* <td>ulistformatter.h</td> * <td>ulistformatter.h</td>
* <td>icu::ListFormatter</td> * <td>icu::ListFormatter</td>

View File

@ -76,7 +76,7 @@ public:
* @return The class ID for all objects of this class. * @return The class ID for all objects of this class.
* @stable ICU 4.0 * @stable ICU 4.0
*/ */
static UClassID U_EXPORT2 getStaticClassID(void); static UClassID U_EXPORT2 getStaticClassID();
/** /**
* Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
@ -89,8 +89,7 @@ public:
* other classes have different class IDs. * other classes have different class IDs.
* @stable ICU 4.0 * @stable ICU 4.0
*/ */
virtual UClassID getDynamicClassID(void) const override; virtual UClassID getDynamicClassID() const override;
/** /**
* Copy constructor. * Copy constructor.

View File

@ -11,6 +11,8 @@
#if U_SHOW_CPLUSPLUS_API #if U_SHOW_CPLUSPLUS_API
#include <optional>
#include "unicode/locid.h" #include "unicode/locid.h"
#include "unicode/stringpiece.h" #include "unicode/stringpiece.h"
#include "unicode/uobject.h" #include "unicode/uobject.h"
@ -133,10 +135,10 @@ U_NAMESPACE_BEGIN
struct LSR; struct LSR;
class LikelySubtags;
class LocaleDistance; class LocaleDistance;
class LocaleLsrIterator; class LocaleLsrIterator;
class UVector; class UVector;
class XLikelySubtags;
/** /**
* Immutable class that picks the best match between a user's desired locales and * Immutable class that picks the best match between a user's desired locales and
@ -678,9 +680,9 @@ private:
int32_t putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode); int32_t putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode);
int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const; std::optional<int32_t> getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const;
const XLikelySubtags &likelySubtags; const LikelySubtags &likelySubtags;
const LocaleDistance &localeDistance; const LocaleDistance &localeDistance;
int32_t thresholdDistance; int32_t thresholdDistance;
int32_t demotionPerDesiredLocale; int32_t demotionPerDesiredLocale;

View File

@ -162,11 +162,11 @@ protected:
T *ptr; T *ptr;
private: private:
// No comparison operators with other LocalPointerBases. // No comparison operators with other LocalPointerBases.
bool operator==(const LocalPointerBase<T> &other); bool operator==(const LocalPointerBase<T> &other) = delete;
bool operator!=(const LocalPointerBase<T> &other); bool operator!=(const LocalPointerBase<T> &other) = delete;
// No ownership sharing: No copy constructor, no assignment operator. // No ownership sharing: No copy constructor, no assignment operator.
LocalPointerBase(const LocalPointerBase<T> &other); LocalPointerBase(const LocalPointerBase<T> &other) = delete;
void operator=(const LocalPointerBase<T> &other); void operator=(const LocalPointerBase<T> &other) = delete;
}; };
/** /**
@ -548,46 +548,60 @@ public:
* @stable ICU 4.4 * @stable ICU 4.4
*/ */
#define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
class LocalPointerClassName : public LocalPointerBase<Type> { \ using LocalPointerClassName = internal::LocalOpenPointer<Type, closeFunction>
public: \
using LocalPointerBase<Type>::operator*; \ #ifndef U_IN_DOXYGEN
using LocalPointerBase<Type>::operator->; \ namespace internal {
explicit LocalPointerClassName(Type *p=nullptr) : LocalPointerBase<Type>(p) {} \ /**
LocalPointerClassName(LocalPointerClassName &&src) noexcept \ * Implementation, do not use directly: use U_DEFINE_LOCAL_OPEN_POINTER.
: LocalPointerBase<Type>(src.ptr) { \ *
src.ptr=nullptr; \ * @see U_DEFINE_LOCAL_OPEN_POINTER
} \ * @internal
/* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \ */
explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \ template <typename Type, auto closeFunction>
: LocalPointerBase<Type>(p.release()) {} \ class LocalOpenPointer : public LocalPointerBase<Type> {
~LocalPointerClassName() { if (ptr != nullptr) { closeFunction(ptr); } } \ using LocalPointerBase<Type>::ptr;
LocalPointerClassName &operator=(LocalPointerClassName &&src) noexcept { \ public:
if (ptr != nullptr) { closeFunction(ptr); } \ using LocalPointerBase<Type>::operator*;
LocalPointerBase<Type>::ptr=src.ptr; \ using LocalPointerBase<Type>::operator->;
src.ptr=nullptr; \ explicit LocalOpenPointer(Type *p=nullptr) : LocalPointerBase<Type>(p) {}
return *this; \ LocalOpenPointer(LocalOpenPointer &&src) noexcept
} \ : LocalPointerBase<Type>(src.ptr) {
/* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \ src.ptr=nullptr;
LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
adoptInstead(p.release()); \
return *this; \
} \
void swap(LocalPointerClassName &other) noexcept { \
Type *temp=LocalPointerBase<Type>::ptr; \
LocalPointerBase<Type>::ptr=other.ptr; \
other.ptr=temp; \
} \
friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) noexcept { \
p1.swap(p2); \
} \
void adoptInstead(Type *p) { \
if (ptr != nullptr) { closeFunction(ptr); } \
ptr=p; \
} \
operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
} \
} }
/* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */
explicit LocalOpenPointer(std::unique_ptr<Type, decltype(closeFunction)> &&p)
: LocalPointerBase<Type>(p.release()) {}
~LocalOpenPointer() { if (ptr != nullptr) { closeFunction(ptr); } }
LocalOpenPointer &operator=(LocalOpenPointer &&src) noexcept {
if (ptr != nullptr) { closeFunction(ptr); }
LocalPointerBase<Type>::ptr=src.ptr;
src.ptr=nullptr;
return *this;
}
/* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */
LocalOpenPointer &operator=(std::unique_ptr<Type, decltype(closeFunction)> &&p) {
adoptInstead(p.release());
return *this;
}
void swap(LocalOpenPointer &other) noexcept {
Type *temp=LocalPointerBase<Type>::ptr;
LocalPointerBase<Type>::ptr=other.ptr;
other.ptr=temp;
}
friend inline void swap(LocalOpenPointer &p1, LocalOpenPointer &p2) noexcept {
p1.swap(p2);
}
void adoptInstead(Type *p) {
if (ptr != nullptr) { closeFunction(ptr); }
ptr=p;
}
operator std::unique_ptr<Type, decltype(closeFunction)> () && {
return std::unique_ptr<Type, decltype(closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction);
}
};
} // namespace internal
#endif
U_NAMESPACE_END U_NAMESPACE_END

View File

@ -195,51 +195,50 @@ class UnicodeString;
class U_COMMON_API Locale : public UObject { class U_COMMON_API Locale : public UObject {
public: public:
/** Useful constant for the Root locale. @stable ICU 4.4 */ /** Useful constant for the Root locale. @stable ICU 4.4 */
static const Locale &U_EXPORT2 getRoot(void); static const Locale& U_EXPORT2 getRoot();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getEnglish(void); static const Locale& U_EXPORT2 getEnglish();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getFrench(void); static const Locale& U_EXPORT2 getFrench();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getGerman(void); static const Locale& U_EXPORT2 getGerman();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getItalian(void); static const Locale& U_EXPORT2 getItalian();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getJapanese(void); static const Locale& U_EXPORT2 getJapanese();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getKorean(void); static const Locale& U_EXPORT2 getKorean();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getChinese(void); static const Locale& U_EXPORT2 getChinese();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getSimplifiedChinese(void); static const Locale& U_EXPORT2 getSimplifiedChinese();
/** Useful constant for this language. @stable ICU 2.0 */ /** Useful constant for this language. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getTraditionalChinese(void); static const Locale& U_EXPORT2 getTraditionalChinese();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getFrance(void); static const Locale& U_EXPORT2 getFrance();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getGermany(void); static const Locale& U_EXPORT2 getGermany();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getItaly(void); static const Locale& U_EXPORT2 getItaly();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getJapan(void); static const Locale& U_EXPORT2 getJapan();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getKorea(void); static const Locale& U_EXPORT2 getKorea();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getChina(void); static const Locale& U_EXPORT2 getChina();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getPRC(void); static const Locale& U_EXPORT2 getPRC();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getTaiwan(void); static const Locale& U_EXPORT2 getTaiwan();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getUK(void); static const Locale& U_EXPORT2 getUK();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getUS(void); static const Locale& U_EXPORT2 getUS();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getCanada(void); static const Locale& U_EXPORT2 getCanada();
/** Useful constant for this country/region. @stable ICU 2.0 */ /** Useful constant for this country/region. @stable ICU 2.0 */
static const Locale &U_EXPORT2 getCanadaFrench(void); static const Locale& U_EXPORT2 getCanadaFrench();
/** /**
* Construct a default locale object, a Locale for the default locale ID. * Construct a default locale object, a Locale for the default locale ID.
@ -274,10 +273,10 @@ public:
* @see uloc_getDefault * @see uloc_getDefault
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
Locale( const char * language, Locale(const char* language,
const char * country = 0, const char* country = nullptr,
const char * variant = 0, const char* variant = nullptr,
const char * keywordsAndValues = 0); const char* keywordsAndValues = nullptr);
/** /**
* Initializes a Locale object from another Locale object. * Initializes a Locale object from another Locale object.
@ -370,7 +369,7 @@ public:
* @system * @system
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
static const Locale& U_EXPORT2 getDefault(void); static const Locale& U_EXPORT2 getDefault();
/** /**
* Sets the default. Normally set once at the beginning of a process, * Sets the default. Normally set once at the beginning of a process,
@ -518,20 +517,20 @@ public:
* If this Locale is already in the maximal form, or not valid, or there is * If this Locale is already in the maximal form, or not valid, or there is
* no data available for maximization, the Locale will be unchanged. * no data available for maximization, the Locale will be unchanged.
* *
* For example, "und-Zzzz" cannot be maximized, since there is no * For example, "sh" cannot be maximized, since there is no
* reasonable maximization. * reasonable maximization.
* *
* Examples: * Examples:
* *
* "und_Zzzz" maximizes to "en_Latn_US"
*
* "en" maximizes to "en_Latn_US" * "en" maximizes to "en_Latn_US"
* *
* "de" maximizes to "de_Latn_US" * "de" maximizes to "de_Latn_DE"
* *
* "sr" maximizes to "sr_Cyrl_RS" * "sr" maximizes to "sr_Cyrl_RS"
* *
* "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.) * "zh_Hani" maximizes to "zh_Hani_CN"
*
* "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.)
* *
* @param status error information if maximizing this Locale failed. * @param status error information if maximizing this Locale failed.
* If this Locale is not well-formed, the error code is * If this Locale is not well-formed, the error code is
@ -792,7 +791,7 @@ public:
* there is no Windows LCID value that corresponds to this locale, returns 0. * there is no Windows LCID value that corresponds to this locale, returns 0.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
uint32_t getLCID(void) const; uint32_t getLCID() const;
/** /**
* Returns whether this locale's script is written right-to-left. * Returns whether this locale's script is written right-to-left.
@ -944,7 +943,7 @@ public:
* Generates a hash code for the locale. * Generates a hash code for the locale.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
int32_t hashCode(void) const; int32_t hashCode() const;
/** /**
* Sets the locale to bogus * Sets the locale to bogus
@ -961,7 +960,7 @@ public:
* @return false if it is a real locale, true if it is a bogus locale * @return false if it is a real locale, true if it is a bogus locale
* @stable ICU 2.1 * @stable ICU 2.1
*/ */
inline UBool isBogus(void) const; inline UBool isBogus() const;
/** /**
* Returns a list of all installed locales. * Returns a list of all installed locales.
@ -1147,7 +1146,7 @@ private:
/** /**
* Initialize the locale cache for commonly used locales * Initialize the locale cache for commonly used locales
*/ */
static Locale *getLocaleCache(void); static Locale* getLocaleCache();
char language[ULOC_LANG_CAPACITY]; char language[ULOC_LANG_CAPACITY];
char script[ULOC_SCRIPT_CAPACITY]; char script[ULOC_SCRIPT_CAPACITY];
@ -1184,6 +1183,7 @@ Locale::operator!=(const Locale& other) const
template<typename StringClass> inline StringClass template<typename StringClass> inline StringClass
Locale::toLanguageTag(UErrorCode& status) const Locale::toLanguageTag(UErrorCode& status) const
{ {
if (U_FAILURE(status)) { return {}; }
StringClass result; StringClass result;
StringByteSink<StringClass> sink(&result); StringByteSink<StringClass> sink(&result);
toLanguageTag(sink, status); toLanguageTag(sink, status);
@ -1211,7 +1211,7 @@ Locale::getScript() const
inline const char * inline const char *
Locale::getVariant() const Locale::getVariant() const
{ {
return &baseName[variantBegin]; return fIsBogus ? "" : &baseName[variantBegin];
} }
inline const char * inline const char *
@ -1223,6 +1223,7 @@ Locale::getName() const
template<typename StringClass, typename OutputIterator> inline void template<typename StringClass, typename OutputIterator> inline void
Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
{ {
if (U_FAILURE(status)) { return; }
LocalPointer<StringEnumeration> keys(createKeywords(status)); LocalPointer<StringEnumeration> keys(createKeywords(status));
if (U_FAILURE(status) || keys.isNull()) { if (U_FAILURE(status) || keys.isNull()) {
return; return;
@ -1240,6 +1241,7 @@ Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
template<typename StringClass, typename OutputIterator> inline void template<typename StringClass, typename OutputIterator> inline void
Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
{ {
if (U_FAILURE(status)) { return; }
LocalPointer<StringEnumeration> keys(createUnicodeKeywords(status)); LocalPointer<StringEnumeration> keys(createUnicodeKeywords(status));
if (U_FAILURE(status) || keys.isNull()) { if (U_FAILURE(status) || keys.isNull()) {
return; return;
@ -1257,6 +1259,7 @@ Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
template<typename StringClass> inline StringClass template<typename StringClass> inline StringClass
Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const
{ {
if (U_FAILURE(status)) { return {}; }
StringClass result; StringClass result;
StringByteSink<StringClass> sink(&result); StringByteSink<StringClass> sink(&result);
getKeywordValue(keywordName, sink, status); getKeywordValue(keywordName, sink, status);
@ -1266,6 +1269,7 @@ Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const
template<typename StringClass> inline StringClass template<typename StringClass> inline StringClass
Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const
{ {
if (U_FAILURE(status)) { return {}; }
StringClass result; StringClass result;
StringByteSink<StringClass> sink(&result); StringByteSink<StringClass> sink(&result);
getUnicodeKeywordValue(keywordName, sink, status); getUnicodeKeywordValue(keywordName, sink, status);
@ -1273,7 +1277,7 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) cons
} }
inline UBool inline UBool
Locale::isBogus(void) const { Locale::isBogus() const {
return fIsBogus; return fIsBogus;
} }

View File

@ -466,7 +466,7 @@ public:
* @return the current normalized code point * @return the current normalized code point
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
UChar32 current(void); UChar32 current();
/** /**
* Return the first character in the normalized text. * Return the first character in the normalized text.
@ -476,7 +476,7 @@ public:
* @return the first normalized code point * @return the first normalized code point
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
UChar32 first(void); UChar32 first();
/** /**
* Return the last character in the normalized text. * Return the last character in the normalized text.
@ -486,7 +486,7 @@ public:
* @return the last normalized code point * @return the last normalized code point
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
UChar32 last(void); UChar32 last();
/** /**
* Return the next character in the normalized text. * Return the next character in the normalized text.
@ -502,7 +502,7 @@ public:
* @return the next normalized code point * @return the next normalized code point
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
UChar32 next(void); UChar32 next();
/** /**
* Return the previous character in the normalized text and decrement. * Return the previous character in the normalized text and decrement.
@ -518,7 +518,7 @@ public:
* @return the previous normalized code point * @return the previous normalized code point
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
UChar32 previous(void); UChar32 previous();
/** /**
* Set the iteration position in the input text that is being normalized, * Set the iteration position in the input text that is being normalized,
@ -536,7 +536,7 @@ public:
* This is equivalent to setIndexOnly(startIndex)). * This is equivalent to setIndexOnly(startIndex)).
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
void reset(void); void reset();
/** /**
* Retrieve the current iteration position in the input text that is * Retrieve the current iteration position in the input text that is
@ -552,7 +552,7 @@ public:
* @return the current index in the input text * @return the current index in the input text
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
int32_t getIndex(void) const; int32_t getIndex() const;
/** /**
* Retrieve the index of the start of the input text. This is the begin index * Retrieve the index of the start of the input text. This is the begin index
@ -562,7 +562,7 @@ public:
* @return the smallest index in the input text where the Normalizer operates * @return the smallest index in the input text where the Normalizer operates
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
int32_t startIndex(void) const; int32_t startIndex() const;
/** /**
* Retrieve the index of the end of the input text. This is the end index * Retrieve the index of the end of the input text. This is the end index
@ -574,7 +574,7 @@ public:
* @return the first index in the input text where the Normalizer does not operate * @return the first index in the input text where the Normalizer does not operate
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
int32_t endIndex(void) const; int32_t endIndex() const;
/** /**
* Returns true when both iterators refer to the same character in the same * Returns true when both iterators refer to the same character in the same
@ -610,7 +610,7 @@ public:
* @return the hash code * @return the hash code
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
int32_t hashCode(void) const; int32_t hashCode() const;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Property access methods // Property access methods
@ -643,7 +643,7 @@ public:
* @see #setMode * @see #setMode
* @deprecated ICU 56 Use Normalizer2 instead. * @deprecated ICU 56 Use Normalizer2 instead.
*/ */
UNormalizationMode getUMode(void) const; UNormalizationMode getUMode() const;
/** /**
* Set options that affect this <code>Normalizer</code>'s operation. * Set options that affect this <code>Normalizer</code>'s operation.
@ -749,7 +749,7 @@ private:
UBool previousNormalize(); UBool previousNormalize();
void init(); void init();
void clearBuffer(void); void clearBuffer();
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Private data // Private data

View File

@ -129,7 +129,7 @@ public:
* @return the current index. * @return the current index.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t getIndex(void) const; inline int32_t getIndex() const;
/** /**
* Set the current parse position. * Set the current parse position.
@ -152,7 +152,7 @@ public:
* error index has not been set. * error index has not been set.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t getErrorIndex(void) const; inline int32_t getErrorIndex() const;
/** /**
* ICU "poor man's RTTI", returns a UClassID for this class. * ICU "poor man's RTTI", returns a UClassID for this class.

View File

@ -206,6 +206,17 @@
# define U_PLATFORM U_PF_UNKNOWN # define U_PLATFORM U_PF_UNKNOWN
#endif #endif
/**
* \def U_REAL_MSVC
* Defined if the compiler is the real MSVC compiler (and not something like
* Clang setting _MSC_VER in order to compile Windows code that requires it).
* Otherwise undefined.
* @internal
*/
#if (defined(_MSC_VER) && !(defined(__clang__) && __clang__)) || defined(U_IN_DOXYGEN)
# define U_REAL_MSVC
#endif
/** /**
* \def CYGWINMSVC * \def CYGWINMSVC
* Defined if this is Windows with Cygwin, but using MSVC rather than gcc. * Defined if this is Windows with Cygwin, but using MSVC rather than gcc.
@ -302,51 +313,6 @@
# define U_PLATFORM_IS_DARWIN_BASED 0 # define U_PLATFORM_IS_DARWIN_BASED 0
#endif #endif
/**
* \def U_HAVE_STDINT_H
* Defines whether stdint.h is available. It is a C99 standard header.
* We used to include inttypes.h which includes stdint.h but we usually do not need
* the additional definitions from inttypes.h.
* @internal
*/
#ifdef U_HAVE_STDINT_H
/* Use the predefined value. */
#elif U_PLATFORM_USES_ONLY_WIN32_API
# if defined(__BORLANDC__) || U_PLATFORM == U_PF_MINGW || (defined(_MSC_VER) && _MSC_VER>=1600)
/* Windows Visual Studio 9 and below do not have stdint.h & inttypes.h, but VS 2010 adds them. */
# define U_HAVE_STDINT_H 1
# else
# define U_HAVE_STDINT_H 0
# endif
#elif U_PLATFORM == U_PF_SOLARIS
/* Solaris has inttypes.h but not stdint.h. */
# define U_HAVE_STDINT_H 0
#elif U_PLATFORM == U_PF_AIX && !defined(_AIX51) && defined(_POWER)
/* PPC AIX <= 4.3 has inttypes.h but not stdint.h. */
# define U_HAVE_STDINT_H 0
#else
# define U_HAVE_STDINT_H 1
#endif
/**
* \def U_HAVE_INTTYPES_H
* Defines whether inttypes.h is available. It is a C99 standard header.
* We include inttypes.h where it is available but stdint.h is not.
* @internal
*/
#ifdef U_HAVE_INTTYPES_H
/* Use the predefined value. */
#elif U_PLATFORM == U_PF_SOLARIS
/* Solaris has inttypes.h but not stdint.h. */
# define U_HAVE_INTTYPES_H 1
#elif U_PLATFORM == U_PF_AIX && !defined(_AIX51) && defined(_POWER)
/* PPC AIX <= 4.3 has inttypes.h but not stdint.h. */
# define U_HAVE_INTTYPES_H 1
#else
/* Most platforms have both inttypes.h and stdint.h, or neither. */
# define U_HAVE_INTTYPES_H U_HAVE_STDINT_H
#endif
/*===========================================================================*/ /*===========================================================================*/
/** @{ Compiler and environment features */ /** @{ Compiler and environment features */
/*===========================================================================*/ /*===========================================================================*/
@ -507,6 +473,8 @@
/* Otherwise use the predefined value. */ /* Otherwise use the predefined value. */
#elif !defined(__cplusplus) #elif !defined(__cplusplus)
# define U_CPLUSPLUS_VERSION 0 # define U_CPLUSPLUS_VERSION 0
#elif __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
# define U_CPLUSPLUS_VERSION 17
#elif __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) #elif __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
# define U_CPLUSPLUS_VERSION 14 # define U_CPLUSPLUS_VERSION 14
#elif __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) #elif __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
@ -754,9 +722,9 @@
/* /*
* Notes: * Notes:
* C++11 and C11 require support for UTF-16 literals * C++11 and C11 require support for UTF-16 literals
* TODO: Fix for plain C. Doesn't work on Mac. * Doesn't work on Mac C11 (see workaround in ptypes.h).
*/ */
# if U_CPLUSPLUS_VERSION >= 11 || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) # if defined(__cplusplus) || !U_PLATFORM_IS_DARWIN_BASED
# define U_HAVE_CHAR16_T 1 # define U_HAVE_CHAR16_T 1
# else # else
# define U_HAVE_CHAR16_T 0 # define U_HAVE_CHAR16_T 0

View File

@ -42,89 +42,25 @@
/* NULL, size_t, wchar_t */ /* NULL, size_t, wchar_t */
#include <stddef.h> #include <stddef.h>
/* /* More platform-specific definitions. */
* If all compilers provided all of the C99 headers and types,
* we would just unconditionally #include <stdint.h> here
* and not need any of the stuff after including platform.h.
*/
/* Find out if we have stdint.h etc. */
#include "unicode/platform.h" #include "unicode/platform.h"
/*===========================================================================*/ /*===========================================================================*/
/* Generic data types */ /* Generic data types */
/*===========================================================================*/ /*===========================================================================*/
/* If your platform does not have the <stdint.h> header, you may
need to edit the typedefs in the #else section below.
Use #if...#else...#endif with predefined compiler macros if possible. */
#if U_HAVE_STDINT_H
/*
* We mostly need <stdint.h> (which defines the standard integer types) but not <inttypes.h>.
* <inttypes.h> includes <stdint.h> and adds the printf/scanf helpers PRId32, SCNx16 etc.
* which we almost never use, plus stuff like imaxabs() which we never use.
*/
#include <stdint.h> #include <stdint.h>
#if U_PLATFORM == U_PF_OS390 // C++11 and C11 both specify that the data type char16_t should exist, C++11
/* The features header is needed to get (u)int64_t sometimes. */ // as a keyword and C11 as a typedef in the uchar.h header file, but not all
#include <features.h> // implementations (looking at you, Apple, spring 2024) actually do this, so
/* z/OS has <stdint.h>, but some versions are missing uint8_t (APAR PK62248). */ // ICU4C must detect and deal with that.
#if !defined(__uint8_t) #if !defined(__cplusplus) && !defined(U_IN_DOXYGEN)
#define __uint8_t 1 # if U_HAVE_CHAR16_T
typedef unsigned char uint8_t; # include <uchar.h>
# else
typedef uint16_t char16_t;
# endif
#endif #endif
#endif /* U_PLATFORM == U_PF_OS390 */
#elif U_HAVE_INTTYPES_H
# include <inttypes.h>
#else /* neither U_HAVE_STDINT_H nor U_HAVE_INTTYPES_H */
/// \cond
#if ! U_HAVE_INT8_T
typedef signed char int8_t;
#endif
#if ! U_HAVE_UINT8_T
typedef unsigned char uint8_t;
#endif
#if ! U_HAVE_INT16_T
typedef signed short int16_t;
#endif
#if ! U_HAVE_UINT16_T
typedef unsigned short uint16_t;
#endif
#if ! U_HAVE_INT32_T
typedef signed int int32_t;
#endif
#if ! U_HAVE_UINT32_T
typedef unsigned int uint32_t;
#endif
#if ! U_HAVE_INT64_T
#ifdef _MSC_VER
typedef signed __int64 int64_t;
#else
typedef signed long long int64_t;
#endif
#endif
#if ! U_HAVE_UINT64_T
#ifdef _MSC_VER
typedef unsigned __int64 uint64_t;
#else
typedef unsigned long long uint64_t;
#endif
#endif
/// \endcond
#endif /* U_HAVE_STDINT_H / U_HAVE_INTTYPES_H */
#endif /* _PTYPES_H */ #endif /* _PTYPES_H */

View File

@ -44,7 +44,7 @@ class UnhandledEngine;
class UStack; class UStack;
#ifndef U_HIDE_DRAFT_API #ifndef U_HIDE_INTERNAL_API
/** /**
* The ExternalBreakEngine class define an abstract interface for the host environment * The ExternalBreakEngine class define an abstract interface for the host environment
* to provide a low level facility to break text for unicode text in script that the text boundary * to provide a low level facility to break text for unicode text in script that the text boundary
@ -103,7 +103,7 @@ class ExternalBreakEngine : public UObject {
int32_t* foundBreaks, int32_t foundBreaksCapacity, int32_t* foundBreaks, int32_t foundBreaksCapacity,
UErrorCode& status) const = 0; UErrorCode& status) const = 0;
}; };
#endif /* U_HIDE_DRAFT_API */ #endif /* U_HIDE_INTERNAL_API */
/** /**
@ -388,14 +388,14 @@ public:
* @return A hash code * @return A hash code
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t hashCode(void) const; virtual int32_t hashCode() const;
/** /**
* Returns the description used to create this iterator * Returns the description used to create this iterator
* @return the description used to create this iterator * @return the description used to create this iterator
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual const UnicodeString& getRules(void) const; virtual const UnicodeString& getRules() const;
//======================================================================= //=======================================================================
// BreakIterator overrides // BreakIterator overrides
@ -425,8 +425,7 @@ public:
* @return An iterator over the text being analyzed. * @return An iterator over the text being analyzed.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual CharacterIterator& getText(void) const override; virtual CharacterIterator& getText() const override;
/** /**
* Get a UText for the text being analyzed. * Get a UText for the text being analyzed.
@ -486,14 +485,14 @@ public:
* @return The offset of the beginning of the text, zero. * @return The offset of the beginning of the text, zero.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t first(void) override; virtual int32_t first() override;
/** /**
* Sets the current iteration position to the end of the text. * Sets the current iteration position to the end of the text.
* @return The text's past-the-end offset. * @return The text's past-the-end offset.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t last(void) override; virtual int32_t last() override;
/** /**
* Advances the iterator either forward or backward the specified number of steps. * Advances the iterator either forward or backward the specified number of steps.
@ -512,14 +511,14 @@ public:
* @return The position of the first boundary after this one. * @return The position of the first boundary after this one.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t next(void) override; virtual int32_t next() override;
/** /**
* Moves the iterator backwards, to the last boundary preceding this one. * Moves the iterator backwards, to the last boundary preceding this one.
* @return The position of the last boundary position preceding this one. * @return The position of the last boundary position preceding this one.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t previous(void) override; virtual int32_t previous() override;
/** /**
* Sets the iterator to refer to the first boundary position following * Sets the iterator to refer to the first boundary position following
@ -557,8 +556,7 @@ public:
* @return The current iteration position. * @return The current iteration position.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t current(void) const override; virtual int32_t current() const override;
/** /**
* Return the status tag from the break rule that determined the boundary at * Return the status tag from the break rule that determined the boundary at
@ -629,7 +627,7 @@ public:
* other classes have different class IDs. * other classes have different class IDs.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UClassID getDynamicClassID(void) const override; virtual UClassID getDynamicClassID() const override;
/** /**
* Returns the class ID for this class. This is useful only for * Returns the class ID for this class. This is useful only for
@ -642,7 +640,7 @@ public:
* @return The class ID for all objects of this class. * @return The class ID for all objects of this class.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
static UClassID U_EXPORT2 getStaticClassID(void); static UClassID U_EXPORT2 getStaticClassID();
#ifndef U_FORCE_HIDE_DEPRECATED_API #ifndef U_FORCE_HIDE_DEPRECATED_API
/** /**
@ -799,7 +797,7 @@ private:
void dumpTables(); void dumpTables();
#endif /* U_HIDE_INTERNAL_API */ #endif /* U_HIDE_INTERNAL_API */
#ifndef U_HIDE_DRAFT_API #ifndef U_HIDE_INTERNAL_API
/** /**
* Register a new external break engine. The external break engine will be adopted. * Register a new external break engine. The external break engine will be adopted.
* Because ICU may choose to cache break engine internally, this must * Because ICU may choose to cache break engine internally, this must
@ -811,7 +809,7 @@ private:
*/ */
static void U_EXPORT2 registerExternalBreakEngine( static void U_EXPORT2 registerExternalBreakEngine(
ExternalBreakEngine* toAdopt, UErrorCode& status); ExternalBreakEngine* toAdopt, UErrorCode& status);
#endif /* U_HIDE_DRAFT_API */ #endif /* U_HIDE_INTERNAL_API */
}; };

View File

@ -209,8 +209,7 @@ public:
* @return number of resources in a given resource. * @return number of resources in a given resource.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
int32_t int32_t getSize() const;
getSize(void) const;
/** /**
* returns a string from a string resource type * returns a string from a string resource type
@ -289,16 +288,14 @@ public:
* @return true if there are more elements, false if there is no more elements * @return true if there are more elements, false if there is no more elements
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
UBool UBool hasNext() const;
hasNext(void) const;
/** /**
* Resets the internal context of a resource so that iteration starts from the first element. * Resets the internal context of a resource so that iteration starts from the first element.
* *
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
void void resetIterator();
resetIterator(void);
/** /**
* Returns the key associated with this resource. Not all the resources have a key - only * Returns the key associated with this resource. Not all the resources have a key - only
@ -307,8 +304,7 @@ public:
* @return a key associated to this resource, or nullptr if it doesn't have a key * @return a key associated to this resource, or nullptr if it doesn't have a key
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
const char* const char* getKey() const;
getKey(void) const;
/** /**
* Gets the locale ID of the resource bundle as a string. * Gets the locale ID of the resource bundle as a string.
@ -317,9 +313,7 @@ public:
* @return the locale ID of the resource bundle as a string * @return the locale ID of the resource bundle as a string
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
const char* const char* getName() const;
getName(void) const;
/** /**
* Returns the type of a resource. Available types are defined in enum UResType * Returns the type of a resource. Available types are defined in enum UResType
@ -327,8 +321,7 @@ public:
* @return type of the given resource. * @return type of the given resource.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
UResType UResType getType() const;
getType(void) const;
/** /**
* Returns the next resource in a given resource or nullptr if there are no more resources * Returns the next resource in a given resource or nullptr if there are no more resources
@ -424,8 +417,7 @@ public:
* @see getVersion * @see getVersion
* @deprecated ICU 2.8 Use getVersion instead. * @deprecated ICU 2.8 Use getVersion instead.
*/ */
const char* const char* getVersionNumber() const;
getVersionNumber(void) const;
#endif /* U_HIDE_DEPRECATED_API */ #endif /* U_HIDE_DEPRECATED_API */
/** /**
@ -445,8 +437,7 @@ public:
* @return a Locale object * @return a Locale object
* @deprecated ICU 2.8 Use getLocale(ULocDataLocaleType type, UErrorCode &status) overload instead. * @deprecated ICU 2.8 Use getLocale(ULocDataLocaleType type, UErrorCode &status) overload instead.
*/ */
const Locale& const Locale& getLocale() const;
getLocale(void) const;
#endif /* U_HIDE_DEPRECATED_API */ #endif /* U_HIDE_DEPRECATED_API */
/** /**

View File

@ -156,14 +156,14 @@ public:
* @return a class ID for this object. * @return a class ID for this object.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UClassID getDynamicClassID(void) const override; virtual UClassID getDynamicClassID() const override;
/** /**
* Return a class ID for this class (not really public) * Return a class ID for this class (not really public)
* @return a class ID for this class * @return a class ID for this class
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
static UClassID U_EXPORT2 getStaticClassID(void); static UClassID U_EXPORT2 getStaticClassID();
protected: protected:
/** /**

View File

@ -25,11 +25,9 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
// Forward declaration: // Forward declaration:
namespace number { namespace number::impl {
namespace impl {
class SimpleModifier; class SimpleModifier;
} }
}
/** /**
* Formats simple patterns like "{1} was born in {0}". * Formats simple patterns like "{1} was born in {0}".

View File

@ -130,13 +130,13 @@ class U_COMMON_API StringPiece : public UMemory {
* @stable ICU 65 * @stable ICU 65
*/ */
template <typename T, template <typename T,
typename = typename std::enable_if< typename = std::enable_if_t<
(std::is_same<decltype(T().data()), const char*>::value (std::is_same_v<decltype(T().data()), const char*>
#if defined(__cpp_char8_t) #if defined(__cpp_char8_t)
|| std::is_same<decltype(T().data()), const char8_t*>::value || std::is_same_v<decltype(T().data()), const char8_t*>
#endif #endif
) && ) &&
std::is_same<decltype(T().size()), size_t>::value>::type> std::is_same_v<decltype(T().size()), size_t>>>
StringPiece(T str) StringPiece(T str)
: ptr_(reinterpret_cast<const char*>(str.data())), : ptr_(reinterpret_cast<const char*>(str.data())),
length_(static_cast<int32_t>(str.size())) {} length_(static_cast<int32_t>(str.size())) {}

View File

@ -25,6 +25,7 @@
#ifndef UCHAR_H #ifndef UCHAR_H
#define UCHAR_H #define UCHAR_H
#include <stdbool.h>
#include "unicode/utypes.h" #include "unicode/utypes.h"
#include "unicode/stringoptions.h" #include "unicode/stringoptions.h"
#include "unicode/ucpmap.h" #include "unicode/ucpmap.h"
@ -668,12 +669,21 @@ typedef enum UProperty {
* @stable ICU 63 * @stable ICU 63
*/ */
UCHAR_VERTICAL_ORIENTATION=0x1018, UCHAR_VERTICAL_ORIENTATION=0x1018,
#ifndef U_HIDE_DRAFT_API
/**
* Enumerated property Identifier_Status.
* Used for UTS #39 General Security Profile for Identifiers
* (https://www.unicode.org/reports/tr39/#General_Security_Profile).
* @draft ICU 75
*/
UCHAR_IDENTIFIER_STATUS=0x1019,
#endif // U_HIDE_DRAFT_API
#ifndef U_HIDE_DEPRECATED_API #ifndef U_HIDE_DEPRECATED_API
/** /**
* One more than the last constant for enumerated/integer Unicode properties. * One more than the last constant for enumerated/integer Unicode properties.
* @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
*/ */
UCHAR_INT_LIMIT=0x1019, UCHAR_INT_LIMIT=0x101A,
#endif // U_HIDE_DEPRECATED_API #endif // U_HIDE_DEPRECATED_API
/** Bitmask property General_Category_Mask. /** Bitmask property General_Category_Mask.
@ -774,12 +784,28 @@ typedef enum UProperty {
UCHAR_SCRIPT_EXTENSIONS=0x7000, UCHAR_SCRIPT_EXTENSIONS=0x7000,
/** First constant for Unicode properties with unusual value types. @stable ICU 4.6 */ /** First constant for Unicode properties with unusual value types. @stable ICU 4.6 */
UCHAR_OTHER_PROPERTY_START=UCHAR_SCRIPT_EXTENSIONS, UCHAR_OTHER_PROPERTY_START=UCHAR_SCRIPT_EXTENSIONS,
#ifndef U_HIDE_DRAFT_API
/**
* Miscellaneous property Identifier_Type.
* Used for UTS #39 General Security Profile for Identifiers
* (https://www.unicode.org/reports/tr39/#General_Security_Profile).
*
* Corresponds to u_hasIDType() and u_getIDTypes().
*
* Each code point maps to a <i>set</i> of UIdentifierType values.
*
* @see u_hasIDType
* @see u_getIDTypes
* @draft ICU 75
*/
UCHAR_IDENTIFIER_TYPE=0x7001,
#endif // U_HIDE_DRAFT_API
#ifndef U_HIDE_DEPRECATED_API #ifndef U_HIDE_DEPRECATED_API
/** /**
* One more than the last constant for Unicode properties with unusual value types. * One more than the last constant for Unicode properties with unusual value types.
* @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
*/ */
UCHAR_OTHER_PROPERTY_LIMIT=0x7001, UCHAR_OTHER_PROPERTY_LIMIT=0x7002,
#endif // U_HIDE_DEPRECATED_API #endif // U_HIDE_DEPRECATED_API
/** Represents a nonexistent or invalid property or property value. @stable ICU 2.4 */ /** Represents a nonexistent or invalid property or property value. @stable ICU 2.4 */
@ -2701,6 +2727,68 @@ typedef enum UVerticalOrientation {
U_VO_UPRIGHT, U_VO_UPRIGHT,
} UVerticalOrientation; } UVerticalOrientation;
#ifndef U_HIDE_DRAFT_API
/**
* Identifier Status constants.
* See https://www.unicode.org/reports/tr39/#Identifier_Status_and_Type.
*
* @see UCHAR_IDENTIFIER_STATUS
* @draft ICU 75
*/
typedef enum UIdentifierStatus {
/*
* Note: UIdentifierStatus constants are parsed by preparseucd.py.
* It matches lines like
* U_ID_STATUS_<Unicode Identifier_Status value name>
*/
/** @draft ICU 75 */
U_ID_STATUS_RESTRICTED,
/** @draft ICU 75 */
U_ID_STATUS_ALLOWED,
} UIdentifierStatus;
/**
* Identifier Type constants.
* See https://www.unicode.org/reports/tr39/#Identifier_Status_and_Type.
*
* @see UCHAR_IDENTIFIER_TYPE
* @draft ICU 75
*/
typedef enum UIdentifierType {
/*
* Note: UIdentifierType constants are parsed by preparseucd.py.
* It matches lines like
* U_ID_TYPE_<Unicode Identifier_Type value name>
*/
/** @draft ICU 75 */
U_ID_TYPE_NOT_CHARACTER,
/** @draft ICU 75 */
U_ID_TYPE_DEPRECATED,
/** @draft ICU 75 */
U_ID_TYPE_DEFAULT_IGNORABLE,
/** @draft ICU 75 */
U_ID_TYPE_NOT_NFKC,
/** @draft ICU 75 */
U_ID_TYPE_NOT_XID,
/** @draft ICU 75 */
U_ID_TYPE_EXCLUSION,
/** @draft ICU 75 */
U_ID_TYPE_OBSOLETE,
/** @draft ICU 75 */
U_ID_TYPE_TECHNICAL,
/** @draft ICU 75 */
U_ID_TYPE_UNCOMMON_USE,
/** @draft ICU 75 */
U_ID_TYPE_LIMITED_USE,
/** @draft ICU 75 */
U_ID_TYPE_INCLUSION,
/** @draft ICU 75 */
U_ID_TYPE_RECOMMENDED,
} UIdentifierType;
#endif // U_HIDE_DRAFT_API
/** /**
* Check a binary Unicode property for a code point. * Check a binary Unicode property for a code point.
* *
@ -3905,6 +3993,59 @@ u_isIDStart(UChar32 c);
U_CAPI UBool U_EXPORT2 U_CAPI UBool U_EXPORT2
u_isIDPart(UChar32 c); u_isIDPart(UChar32 c);
#ifndef U_HIDE_DRAFT_API
/**
* Does the set of Identifier_Type values code point c contain the given type?
*
* Used for UTS #39 General Security Profile for Identifiers
* (https://www.unicode.org/reports/tr39/#General_Security_Profile).
*
* Each code point maps to a <i>set</i> of UIdentifierType values.
*
* @param c code point
* @param type Identifier_Type to check
* @return true if type is in Identifier_Type(c)
* @draft ICU 75
*/
U_CAPI bool U_EXPORT2
u_hasIDType(UChar32 c, UIdentifierType type);
/**
* Writes code point c's Identifier_Type as a list of UIdentifierType values
* to the output types array and returns the number of types.
*
* Used for UTS #39 General Security Profile for Identifiers
* (https://www.unicode.org/reports/tr39/#General_Security_Profile).
*
* Each code point maps to a <i>set</i> of UIdentifierType values.
* There is always at least one type.
* The order of output values is undefined.
* Each type is output at most once;
* there cannot be more output values than UIdentifierType constants.
* In addition, only some of the types can be combined with others,
* and usually only a small number of types occur together.
* Future versions might add additional types.
* See UTS #39 and its data files for details.
*
* If there are more than capacity types to be written, then
* U_BUFFER_OVERFLOW_ERROR is set and the number of types is returned.
* (Usual ICU buffer handling behavior.)
*
* @param c code point
* @param types output array
* @param capacity capacity of the array
* @param pErrorCode Standard ICU error code. Its input value must
* pass the U_SUCCESS() test, or else the function returns
* immediately. Check for U_FAILURE() on output or use with
* function chaining. (See User Guide for details.)
* @return number of values in c's Identifier_Type,
* written to types unless U_BUFFER_OVERFLOW_ERROR indicates insufficient capacity
* @draft ICU 75
*/
U_CAPI int32_t U_EXPORT2
u_getIDTypes(UChar32 c, UIdentifierType *types, int32_t capacity, UErrorCode *pErrorCode);
#endif // U_HIDE_DRAFT_API
/** /**
* Determines if the specified character should be regarded * Determines if the specified character should be regarded
* as an ignorable character in an identifier, * as an ignorable character in an identifier,

View File

@ -126,7 +126,7 @@ public:
* @return the hash code. * @return the hash code.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t hashCode(void) const override; virtual int32_t hashCode() const override;
/** /**
* Returns a new UCharCharacterIterator referring to the same * Returns a new UCharCharacterIterator referring to the same
@ -144,7 +144,7 @@ public:
* @return the first code unit in its iteration range. * @return the first code unit in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t first(void) override; virtual char16_t first() override;
/** /**
* Sets the iterator to refer to the first code unit in its * Sets the iterator to refer to the first code unit in its
@ -154,7 +154,7 @@ public:
* @return the first code unit in its iteration range * @return the first code unit in its iteration range
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t firstPostInc(void) override; virtual char16_t firstPostInc() override;
/** /**
* Sets the iterator to refer to the first code point in its * Sets the iterator to refer to the first code point in its
@ -165,7 +165,7 @@ public:
* @return the first code point in its iteration range * @return the first code point in its iteration range
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 first32(void) override; virtual UChar32 first32() override;
/** /**
* Sets the iterator to refer to the first code point in its * Sets the iterator to refer to the first code point in its
@ -175,7 +175,7 @@ public:
* @return the first code point in its iteration range. * @return the first code point in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 first32PostInc(void) override; virtual UChar32 first32PostInc() override;
/** /**
* Sets the iterator to refer to the last code unit in its * Sets the iterator to refer to the last code unit in its
@ -184,7 +184,7 @@ public:
* @return the last code unit in its iteration range. * @return the last code unit in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t last(void) override; virtual char16_t last() override;
/** /**
* Sets the iterator to refer to the last code point in its * Sets the iterator to refer to the last code point in its
@ -193,7 +193,7 @@ public:
* @return the last code point in its iteration range. * @return the last code point in its iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 last32(void) override; virtual UChar32 last32() override;
/** /**
* Sets the iterator to refer to the "position"-th code unit * Sets the iterator to refer to the "position"-th code unit
@ -223,14 +223,14 @@ public:
* @return the code unit the iterator currently refers to. * @return the code unit the iterator currently refers to.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t current(void) const override; virtual char16_t current() const override;
/** /**
* Returns the code point the iterator currently refers to. * Returns the code point the iterator currently refers to.
* @return the code point the iterator currently refers to. * @return the code point the iterator currently refers to.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 current32(void) const override; virtual UChar32 current32() const override;
/** /**
* Advances to the next code unit in the iteration range (toward * Advances to the next code unit in the iteration range (toward
@ -239,7 +239,7 @@ public:
* @return the next code unit in the iteration range. * @return the next code unit in the iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t next(void) override; virtual char16_t next() override;
/** /**
* Gets the current code unit for returning and advances to the next code unit * Gets the current code unit for returning and advances to the next code unit
@ -249,7 +249,7 @@ public:
* @return the current code unit. * @return the current code unit.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t nextPostInc(void) override; virtual char16_t nextPostInc() override;
/** /**
* Advances to the next code point in the iteration range (toward * Advances to the next code point in the iteration range (toward
@ -261,7 +261,7 @@ public:
* @return the next code point in the iteration range. * @return the next code point in the iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 next32(void) override; virtual UChar32 next32() override;
/** /**
* Gets the current code point for returning and advances to the next code point * Gets the current code point for returning and advances to the next code point
@ -271,7 +271,7 @@ public:
* @return the current point. * @return the current point.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 next32PostInc(void) override; virtual UChar32 next32PostInc() override;
/** /**
* Returns false if there are no more code units or code points * Returns false if there are no more code units or code points
@ -291,7 +291,7 @@ public:
* @return the previous code unit in the iteration range. * @return the previous code unit in the iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual char16_t previous(void) override; virtual char16_t previous() override;
/** /**
* Advances to the previous code point in the iteration range (toward * Advances to the previous code point in the iteration range (toward
@ -300,7 +300,7 @@ public:
* @return the previous code point in the iteration range. * @return the previous code point in the iteration range.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UChar32 previous32(void) override; virtual UChar32 previous32() override;
/** /**
* Returns false if there are no more code units or code points * Returns false if there are no more code units or code points
@ -363,14 +363,14 @@ public:
* @return a class ID for this class * @return a class ID for this class
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
static UClassID U_EXPORT2 getStaticClassID(void); static UClassID U_EXPORT2 getStaticClassID();
/** /**
* Return a class ID for this object (not really public) * Return a class ID for this object (not really public)
* @return a class ID for this object. * @return a class ID for this object.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UClassID getDynamicClassID(void) const override; virtual UClassID getDynamicClassID() const override;
protected: protected:
/** /**

View File

@ -344,8 +344,6 @@ ucnv_compareNames(const char *name1, const char *name2);
* other than its an alias starting with the letters "cp". Please do not * other than its an alias starting with the letters "cp". Please do not
* associate any meaning to these aliases.</p> * associate any meaning to these aliases.</p>
* *
* \snippet samples/ucnv/convsamp.cpp ucnv_open
*
* @param converterName Name of the coded character set table. * @param converterName Name of the coded character set table.
* This may have options appended to the string. * This may have options appended to the string.
* IANA alias character set names, IBM CCSIDs starting with "ibm-", * IANA alias character set names, IBM CCSIDs starting with "ibm-",
@ -1986,7 +1984,6 @@ ucnv_usesFallback(const UConverter *cnv);
* instead of the input signature bytes. * instead of the input signature bytes.
* <p> * <p>
* Usage: * Usage:
* \snippet samples/ucnv/convsamp.cpp ucnv_detectUnicodeSignature
* *
* @param source The source string in which the signature should be detected. * @param source The source string in which the signature should be detected.
* @param sourceLength Length of the input string, or -1 if terminated with a NUL byte. * @param sourceLength Length of the input string, or -1 if terminated with a NUL byte.

View File

@ -413,6 +413,17 @@
# define UCONFIG_NO_FORMATTING 0 # define UCONFIG_NO_FORMATTING 0
#endif #endif
/**
* \def UCONFIG_NO_MF2
* This switch turns off the experimental MessageFormat 2.0 API.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
#ifndef UCONFIG_NO_MF2
# define UCONFIG_NO_MF2 0
#endif
/** /**
* \def UCONFIG_NO_TRANSLITERATION * \def UCONFIG_NO_TRANSLITERATION
* This switch turns off transliteration. * This switch turns off transliteration.

View File

@ -399,6 +399,9 @@ uloc_setDefault(const char* localeID,
/** /**
* Gets the language code for the specified locale. * Gets the language code for the specified locale.
* *
* This function may return with a failure error code for certain kinds of inputs
* but does not fully check for well-formed locale IDs / language tags.
*
* @param localeID the locale to get the ISO language code with * @param localeID the locale to get the ISO language code with
* @param language the language code for localeID * @param language the language code for localeID
* @param languageCapacity the size of the language buffer to store the * @param languageCapacity the size of the language buffer to store the
@ -417,6 +420,9 @@ uloc_getLanguage(const char* localeID,
/** /**
* Gets the script code for the specified locale. * Gets the script code for the specified locale.
* *
* This function may return with a failure error code for certain kinds of inputs
* but does not fully check for well-formed locale IDs / language tags.
*
* @param localeID the locale to get the ISO language code with * @param localeID the locale to get the ISO language code with
* @param script the language code for localeID * @param script the language code for localeID
* @param scriptCapacity the size of the language buffer to store the * @param scriptCapacity the size of the language buffer to store the
@ -435,6 +441,9 @@ uloc_getScript(const char* localeID,
/** /**
* Gets the country code for the specified locale. * Gets the country code for the specified locale.
* *
* This function may return with a failure error code for certain kinds of inputs
* but does not fully check for well-formed locale IDs / language tags.
*
* @param localeID the locale to get the country code with * @param localeID the locale to get the country code with
* @param country the country code for localeID * @param country the country code for localeID
* @param countryCapacity the size of the country buffer to store the * @param countryCapacity the size of the country buffer to store the
@ -453,6 +462,9 @@ uloc_getCountry(const char* localeID,
/** /**
* Gets the variant code for the specified locale. * Gets the variant code for the specified locale.
* *
* This function may return with a failure error code for certain kinds of inputs
* but does not fully check for well-formed locale IDs / language tags.
*
* @param localeID the locale to get the variant code with * @param localeID the locale to get the variant code with
* @param variant the variant code for localeID * @param variant the variant code for localeID
* @param variantCapacity the size of the variant buffer to store the * @param variantCapacity the size of the variant buffer to store the
@ -471,6 +483,10 @@ uloc_getVariant(const char* localeID,
/** /**
* Gets the full name for the specified locale. * Gets the full name for the specified locale.
*
* This function may return with a failure error code for certain kinds of inputs
* but does not fully check for well-formed locale IDs / language tags.
*
* Note: This has the effect of 'canonicalizing' the ICU locale ID to * Note: This has the effect of 'canonicalizing' the ICU locale ID to
* a certain extent. Upper and lower case are set as needed. * a certain extent. Upper and lower case are set as needed.
* It does NOT map aliased names in any way. * It does NOT map aliased names in any way.
@ -1158,19 +1174,20 @@ uloc_getLocaleForLCID(uint32_t hostID, char *locale, int32_t localeCapacity,
* *
* If localeID is already in the maximal form, or there is no data available * If localeID is already in the maximal form, or there is no data available
* for maximization, it will be copied to the output buffer. For example, * for maximization, it will be copied to the output buffer. For example,
* "und-Zzzz" cannot be maximized, since there is no reasonable maximization. * "sh" cannot be maximized, since there is no reasonable maximization.
* *
* Examples: * Examples:
* *
* "und_Zzzz" maximizes to "en_Latn_US"
*
* "en" maximizes to "en_Latn_US" * "en" maximizes to "en_Latn_US"
* *
* "de" maximizes to "de_Latn_US" * "de" maximizes to "de_Latn_DE"
* *
* "sr" maximizes to "sr_Cyrl_RS" * "sr" maximizes to "sr_Cyrl_RS"
* *
* "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.) * "zh_Hani" maximizes to "zh_Hani_CN"
* *
* "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.)
* *
* @param localeID The locale to maximize * @param localeID The locale to maximize
* @param maximizedLocaleID The maximized locale * @param maximizedLocaleID The maximized locale

View File

@ -74,7 +74,7 @@ typedef struct ULocaleBuilder ULocaleBuilder;
* @draft ICU 74 * @draft ICU 74
*/ */
U_CAPI ULocaleBuilder* U_EXPORT2 U_CAPI ULocaleBuilder* U_EXPORT2
ulocbld_open(); ulocbld_open(void);
/** /**
* Close the builder and destroy it's internal states. * Close the builder and destroy it's internal states.

View File

@ -370,22 +370,14 @@ typedef int8_t UBool;
#if 1 #if 1
// #if 1 is normal. UChar defaults to char16_t in C++. // #if 1 is normal. UChar defaults to char16_t in C++.
// For configuration testing of UChar=uint16_t temporarily change this to #if 0. // For configuration testing of UChar=uint16_t temporarily change this to #if 0.
// The intltest Makefile #defines UCHAR_TYPE=char16_t, #else
// so we only #define it to uint16_t if it is undefined so far.
#elif !defined(UCHAR_TYPE)
# define UCHAR_TYPE uint16_t # define UCHAR_TYPE uint16_t
#endif #endif
#if defined(U_COMBINED_IMPLEMENTATION) || defined(U_COMMON_IMPLEMENTATION) || \ #if defined(U_ALL_IMPLEMENTATION) || !defined(UCHAR_TYPE)
defined(U_I18N_IMPLEMENTATION) || defined(U_IO_IMPLEMENTATION)
// Inside the ICU library code, never configurable.
typedef char16_t UChar; typedef char16_t UChar;
#elif defined(UCHAR_TYPE)
typedef UCHAR_TYPE UChar;
#elif U_CPLUSPLUS_VERSION != 0
typedef char16_t UChar; // C++
#else #else
typedef uint16_t UChar; // C typedef UCHAR_TYPE UChar;
#endif #endif
/** /**

View File

@ -83,7 +83,7 @@ public:
* @return The class ID for all objects of this class. * @return The class ID for all objects of this class.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
static UClassID U_EXPORT2 getStaticClassID(void); static UClassID U_EXPORT2 getStaticClassID();
/** /**
* Returns a unique class ID <b>polymorphically</b>. This method * Returns a unique class ID <b>polymorphically</b>. This method
@ -100,7 +100,7 @@ public:
* different class IDs. * different class IDs.
* @stable ICU 2.4 * @stable ICU 2.4
*/ */
virtual UClassID getDynamicClassID(void) const override = 0; virtual UClassID getDynamicClassID() const override = 0;
/** /**
* Set the data object associated with this functor. The data * Set the data object associated with this functor. The data

View File

@ -333,7 +333,7 @@ public:
* @see setToBogus() * @see setToBogus()
* @stable ICU 4.0 * @stable ICU 4.0
*/ */
inline UBool isBogus(void) const; inline UBool isBogus() const;
/** /**
* Make this UnicodeSet object invalid. * Make this UnicodeSet object invalid.
@ -522,7 +522,7 @@ public:
* @see Object#hashCode() * @see Object#hashCode()
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual int32_t hashCode(void) const; virtual int32_t hashCode() const;
/** /**
* Get a UnicodeSet pointer from a USet * Get a UnicodeSet pointer from a USet
@ -792,7 +792,7 @@ public:
* @stable ICU 2.0 * @stable ICU 2.0
* @see getRangeCount * @see getRangeCount
*/ */
virtual int32_t size(void) const; virtual int32_t size() const;
/** /**
* Returns <tt>true</tt> if this set contains no elements. * Returns <tt>true</tt> if this set contains no elements.
@ -800,7 +800,7 @@ public:
* @return <tt>true</tt> if this set contains no elements. * @return <tt>true</tt> if this set contains no elements.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UBool isEmpty(void) const; virtual UBool isEmpty() const;
/** /**
* @return true if this set contains multi-character strings or the empty string. * @return true if this set contains multi-character strings or the empty string.
@ -1394,7 +1394,7 @@ public:
* A frozen set will not be modified. * A frozen set will not be modified.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
virtual UnicodeSet& clear(void); virtual UnicodeSet& clear();
/** /**
* Close this set over the given attribute. For the attribute * Close this set over the given attribute. For the attribute
@ -1440,7 +1440,7 @@ public:
* @see #getRangeEnd * @see #getRangeEnd
* @stable ICU 2.4 * @stable ICU 2.4
*/ */
virtual int32_t getRangeCount(void) const; virtual int32_t getRangeCount() const;
/** /**
* Iteration method that returns the first character in the * Iteration method that returns the first character in the
@ -1529,7 +1529,7 @@ public:
* @return The class ID for all objects of this class. * @return The class ID for all objects of this class.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
static UClassID U_EXPORT2 getStaticClassID(void); static UClassID U_EXPORT2 getStaticClassID();
/** /**
* Implement UnicodeFunctor API. * Implement UnicodeFunctor API.
@ -1539,9 +1539,9 @@ public:
* different class IDs. * different class IDs.
* @stable ICU 2.4 * @stable ICU 2.4
*/ */
virtual UClassID getDynamicClassID(void) const override; virtual UClassID getDynamicClassID() const override;
private: private:
// Private API for the USet API // Private API for the USet API
@ -1602,7 +1602,7 @@ private:
bool ensureBufferCapacity(int32_t newLen); bool ensureBufferCapacity(int32_t newLen);
void swapBuffers(void); void swapBuffers();
UBool allocateStrings(UErrorCode &status); UBool allocateStrings(UErrorCode &status);
int32_t stringsSize() const; int32_t stringsSize() const;

View File

@ -1612,8 +1612,8 @@ public:
*/ */
inline int32_t extract(int32_t start, inline int32_t extract(int32_t start,
int32_t startLength, int32_t startLength,
char *target, char* target,
const char *codepage = 0) const; const char* codepage = nullptr) const;
/** /**
* Copy the characters in the range * Copy the characters in the range
@ -1759,7 +1759,7 @@ public:
* @see countChar32 * @see countChar32
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t length(void) const; inline int32_t length() const;
/** /**
* Count Unicode code points in the length char16_t code units of the string. * Count Unicode code points in the length char16_t code units of the string.
@ -1808,7 +1808,7 @@ public:
* @return true if this string contains 0 characters, false otherwise. * @return true if this string contains 0 characters, false otherwise.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline UBool isEmpty(void) const; inline UBool isEmpty() const;
/** /**
* Return the capacity of the internal buffer of the UnicodeString object. * Return the capacity of the internal buffer of the UnicodeString object.
@ -1819,7 +1819,7 @@ public:
* @see getBuffer * @see getBuffer
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t getCapacity(void) const; inline int32_t getCapacity() const;
/* Other operations */ /* Other operations */
@ -1828,7 +1828,7 @@ public:
* @return The hash code of this UnicodeString. * @return The hash code of this UnicodeString.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline int32_t hashCode(void) const; inline int32_t hashCode() const;
/** /**
* Determine if this object contains a valid string. * Determine if this object contains a valid string.
@ -1842,8 +1842,7 @@ public:
* @see setToBogus() * @see setToBogus()
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline UBool isBogus(void) const; inline UBool isBogus() const;
//======================================== //========================================
// Write operations // Write operations
@ -2624,8 +2623,7 @@ public:
* @return a reference to this * @return a reference to this
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
UnicodeString& trim(void); UnicodeString& trim();
/* Miscellaneous operations */ /* Miscellaneous operations */
@ -2634,7 +2632,7 @@ public:
* @return a reference to this * @return a reference to this
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
inline UnicodeString& reverse(void); inline UnicodeString& reverse();
/** /**
* Reverse the range [`start`, `start + length`) in * Reverse the range [`start`, `start + length`) in
@ -2653,7 +2651,7 @@ public:
* @return A reference to this. * @return A reference to this.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
UnicodeString& toUpper(void); UnicodeString& toUpper();
/** /**
* Convert the characters in this to UPPER CASE following the conventions of * Convert the characters in this to UPPER CASE following the conventions of
@ -2670,7 +2668,7 @@ public:
* @return A reference to this. * @return A reference to this.
* @stable ICU 2.0 * @stable ICU 2.0
*/ */
UnicodeString& toLower(void); UnicodeString& toLower();
/** /**
* Convert the characters in this to lower case following the conventions of * Convert the characters in this to lower case following the conventions of
@ -3590,12 +3588,12 @@ private:
int32_t length); int32_t length);
// calculate hash code // calculate hash code
int32_t doHashCode(void) const; int32_t doHashCode() const;
// get pointer to start of array // get pointer to start of array
// these do not check for kOpenGetBuffer, unlike the public getBuffer() function // these do not check for kOpenGetBuffer, unlike the public getBuffer() function
inline char16_t* getArrayStart(void); inline char16_t* getArrayStart();
inline const char16_t* getArrayStart(void) const; inline const char16_t* getArrayStart() const;
inline UBool hasShortLength() const; inline UBool hasShortLength() const;
inline int32_t getShortLength() const; inline int32_t getShortLength() const;
@ -3622,7 +3620,7 @@ private:
UBool allocate(int32_t capacity); UBool allocate(int32_t capacity);
// release the array if owned // release the array if owned
void releaseArray(void); void releaseArray();
// turn a bogus string into an empty one // turn a bogus string into an empty one
void unBogus(); void unBogus();
@ -3686,7 +3684,7 @@ private:
UBool cloneArrayIfNeeded(int32_t newCapacity = -1, UBool cloneArrayIfNeeded(int32_t newCapacity = -1,
int32_t growCapacity = -1, int32_t growCapacity = -1,
UBool doCopyArray = true, UBool doCopyArray = true,
int32_t **pBufferToDelete = 0, int32_t** pBufferToDelete = nullptr,
UBool forceClone = false); UBool forceClone = false);
/** /**
@ -3702,9 +3700,9 @@ private:
UStringCaseMapper *stringCaseMapper); UStringCaseMapper *stringCaseMapper);
// ref counting // ref counting
void addRef(void); void addRef();
int32_t removeRef(void); int32_t removeRef();
int32_t refCount(void) const; int32_t refCount() const;
// constants // constants
enum { enum {
@ -4510,7 +4508,7 @@ UnicodeString::extract(int32_t start,
{ {
// This dstSize value will be checked explicitly // This dstSize value will be checked explicitly
return extract(start, _length, dst, dst!=0 ? 0xffffffff : 0, codepage); return extract(start, _length, dst, dst != nullptr ? 0xffffffff : 0, codepage);
} }
#endif #endif

View File

@ -272,6 +272,7 @@
#define u_getDataVersion U_ICU_ENTRY_POINT_RENAME(u_getDataVersion) #define u_getDataVersion U_ICU_ENTRY_POINT_RENAME(u_getDataVersion)
#define u_getDefaultConverter U_ICU_ENTRY_POINT_RENAME(u_getDefaultConverter) #define u_getDefaultConverter U_ICU_ENTRY_POINT_RENAME(u_getDefaultConverter)
#define u_getFC_NFKC_Closure U_ICU_ENTRY_POINT_RENAME(u_getFC_NFKC_Closure) #define u_getFC_NFKC_Closure U_ICU_ENTRY_POINT_RENAME(u_getFC_NFKC_Closure)
#define u_getIDTypes U_ICU_ENTRY_POINT_RENAME(u_getIDTypes)
#define u_getISOComment U_ICU_ENTRY_POINT_RENAME(u_getISOComment) #define u_getISOComment U_ICU_ENTRY_POINT_RENAME(u_getISOComment)
#define u_getIntPropertyMap U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMap) #define u_getIntPropertyMap U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMap)
#define u_getIntPropertyMaxValue U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMaxValue) #define u_getIntPropertyMaxValue U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMaxValue)
@ -289,6 +290,7 @@
#define u_getVersion U_ICU_ENTRY_POINT_RENAME(u_getVersion) #define u_getVersion U_ICU_ENTRY_POINT_RENAME(u_getVersion)
#define u_get_stdout U_ICU_ENTRY_POINT_RENAME(u_get_stdout) #define u_get_stdout U_ICU_ENTRY_POINT_RENAME(u_get_stdout)
#define u_hasBinaryProperty U_ICU_ENTRY_POINT_RENAME(u_hasBinaryProperty) #define u_hasBinaryProperty U_ICU_ENTRY_POINT_RENAME(u_hasBinaryProperty)
#define u_hasIDType U_ICU_ENTRY_POINT_RENAME(u_hasIDType)
#define u_init U_ICU_ENTRY_POINT_RENAME(u_init) #define u_init U_ICU_ENTRY_POINT_RENAME(u_init)
#define u_isIDIgnorable U_ICU_ENTRY_POINT_RENAME(u_isIDIgnorable) #define u_isIDIgnorable U_ICU_ENTRY_POINT_RENAME(u_isIDIgnorable)
#define u_isIDPart U_ICU_ENTRY_POINT_RENAME(u_isIDPart) #define u_isIDPart U_ICU_ENTRY_POINT_RENAME(u_isIDPart)
@ -1192,16 +1194,20 @@
#define ulocimp_canonicalize U_ICU_ENTRY_POINT_RENAME(ulocimp_canonicalize) #define ulocimp_canonicalize U_ICU_ENTRY_POINT_RENAME(ulocimp_canonicalize)
#define ulocimp_forLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_forLanguageTag) #define ulocimp_forLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_forLanguageTag)
#define ulocimp_getBaseName U_ICU_ENTRY_POINT_RENAME(ulocimp_getBaseName) #define ulocimp_getBaseName U_ICU_ENTRY_POINT_RENAME(ulocimp_getBaseName)
#define ulocimp_getCountry U_ICU_ENTRY_POINT_RENAME(ulocimp_getCountry)
#define ulocimp_getKeywordValue U_ICU_ENTRY_POINT_RENAME(ulocimp_getKeywordValue) #define ulocimp_getKeywordValue U_ICU_ENTRY_POINT_RENAME(ulocimp_getKeywordValue)
#define ulocimp_getKeywords U_ICU_ENTRY_POINT_RENAME(ulocimp_getKeywords) #define ulocimp_getKeywords U_ICU_ENTRY_POINT_RENAME(ulocimp_getKeywords)
#define ulocimp_getKnownCanonicalizedLocaleForTest U_ICU_ENTRY_POINT_RENAME(ulocimp_getKnownCanonicalizedLocaleForTest) #define ulocimp_getKnownCanonicalizedLocaleForTest U_ICU_ENTRY_POINT_RENAME(ulocimp_getKnownCanonicalizedLocaleForTest)
#define ulocimp_getLanguage U_ICU_ENTRY_POINT_RENAME(ulocimp_getLanguage) #define ulocimp_getLanguage U_ICU_ENTRY_POINT_RENAME(ulocimp_getLanguage)
#define ulocimp_getName U_ICU_ENTRY_POINT_RENAME(ulocimp_getName) #define ulocimp_getName U_ICU_ENTRY_POINT_RENAME(ulocimp_getName)
#define ulocimp_getParent U_ICU_ENTRY_POINT_RENAME(ulocimp_getParent)
#define ulocimp_getRegion U_ICU_ENTRY_POINT_RENAME(ulocimp_getRegion)
#define ulocimp_getRegionForSupplementalData U_ICU_ENTRY_POINT_RENAME(ulocimp_getRegionForSupplementalData) #define ulocimp_getRegionForSupplementalData U_ICU_ENTRY_POINT_RENAME(ulocimp_getRegionForSupplementalData)
#define ulocimp_getScript U_ICU_ENTRY_POINT_RENAME(ulocimp_getScript) #define ulocimp_getScript U_ICU_ENTRY_POINT_RENAME(ulocimp_getScript)
#define ulocimp_getSubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_getSubtags)
#define ulocimp_getVariant U_ICU_ENTRY_POINT_RENAME(ulocimp_getVariant)
#define ulocimp_isCanonicalizedLocaleForTest U_ICU_ENTRY_POINT_RENAME(ulocimp_isCanonicalizedLocaleForTest) #define ulocimp_isCanonicalizedLocaleForTest U_ICU_ENTRY_POINT_RENAME(ulocimp_isCanonicalizedLocaleForTest)
#define ulocimp_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_minimizeSubtags) #define ulocimp_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_minimizeSubtags)
#define ulocimp_setKeywordValue U_ICU_ENTRY_POINT_RENAME(ulocimp_setKeywordValue)
#define ulocimp_toBcpKey U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpKey) #define ulocimp_toBcpKey U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpKey)
#define ulocimp_toBcpType U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpType) #define ulocimp_toBcpType U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpType)
#define ulocimp_toLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_toLanguageTag) #define ulocimp_toLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_toLanguageTag)
@ -1800,6 +1806,7 @@
#define usnum_multiplyByPowerOfTen U_ICU_ENTRY_POINT_RENAME(usnum_multiplyByPowerOfTen) #define usnum_multiplyByPowerOfTen U_ICU_ENTRY_POINT_RENAME(usnum_multiplyByPowerOfTen)
#define usnum_openForInt64 U_ICU_ENTRY_POINT_RENAME(usnum_openForInt64) #define usnum_openForInt64 U_ICU_ENTRY_POINT_RENAME(usnum_openForInt64)
#define usnum_roundTo U_ICU_ENTRY_POINT_RENAME(usnum_roundTo) #define usnum_roundTo U_ICU_ENTRY_POINT_RENAME(usnum_roundTo)
#define usnum_setMaximumIntegerDigits U_ICU_ENTRY_POINT_RENAME(usnum_setMaximumIntegerDigits)
#define usnum_setMinimumFractionDigits U_ICU_ENTRY_POINT_RENAME(usnum_setMinimumFractionDigits) #define usnum_setMinimumFractionDigits U_ICU_ENTRY_POINT_RENAME(usnum_setMinimumFractionDigits)
#define usnum_setMinimumIntegerDigits U_ICU_ENTRY_POINT_RENAME(usnum_setMinimumIntegerDigits) #define usnum_setMinimumIntegerDigits U_ICU_ENTRY_POINT_RENAME(usnum_setMinimumIntegerDigits)
#define usnum_setSign U_ICU_ENTRY_POINT_RENAME(usnum_setSign) #define usnum_setSign U_ICU_ENTRY_POINT_RENAME(usnum_setSign)

View File

@ -500,6 +500,9 @@ typedef enum UScriptCode {
/** @stable ICU 72 */ /** @stable ICU 72 */
USCRIPT_NAG_MUNDARI = 199,/* Nagm */ USCRIPT_NAG_MUNDARI = 199,/* Nagm */
/** @stable ICU 75 */
USCRIPT_ARABIC_NASTALIQ = 200, /* Aran */
#ifndef U_HIDE_DEPRECATED_API #ifndef U_HIDE_DEPRECATED_API
/** /**
* One more than the highest normal UScriptCode value. * One more than the highest normal UScriptCode value.
@ -507,7 +510,7 @@ typedef enum UScriptCode {
* *
* @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
*/ */
USCRIPT_CODE_LIMIT = 200 USCRIPT_CODE_LIMIT = 201
#endif // U_HIDE_DEPRECATED_API #endif // U_HIDE_DEPRECATED_API
} UScriptCode; } UScriptCode;

View File

@ -109,7 +109,6 @@ enum {
*/ */
USET_ADD_CASE_MAPPINGS = 4, USET_ADD_CASE_MAPPINGS = 4,
#ifndef U_HIDE_DRAFT_API
/** /**
* Enable case insensitive matching. * Enable case insensitive matching.
* Same as USET_CASE_INSENSITIVE but using only Simple_Case_Folding (scf) mappings, * Same as USET_CASE_INSENSITIVE but using only Simple_Case_Folding (scf) mappings,
@ -120,10 +119,9 @@ enum {
* regular expression implementations where only Simple_Case_Folding mappings are used, * regular expression implementations where only Simple_Case_Folding mappings are used,
* such as in ECMAScript (JavaScript) regular expressions. * such as in ECMAScript (JavaScript) regular expressions.
* *
* @draft ICU 73 * @stable ICU 73
*/ */
USET_SIMPLE_CASE_INSENSITIVE = 6 USET_SIMPLE_CASE_INSENSITIVE = 6
#endif // U_HIDE_DRAFT_API
}; };
/** /**

Some files were not shown because too many files have changed in this diff Show More