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/
Comment: International Components for Unicode
Copyright: 1991-2021, Unicode
Copyright: 2016-2024, Unicode, Inc.
License: Unicode
Files: ./thirdparty/jpeg-compressor/

View File

@ -468,7 +468,7 @@ if env["builtin_icu4c"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
icu_data_name = "icudt74l.dat"
icu_data_name = "icudt75l.dat"
if env.editor_build:
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]
icu_data_name = "icudt74l.dat"
icu_data_name = "icudt75l.dat"
if env["static_icu_data"]:
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
- Upstream: https://github.com/unicode-org/icu
- Version: 74.2 (2d029329c82c7792b985024b2bdab5fc7278fbc8, 2023)
- Version: 75.1 (7750081bda4b3bc1768ae03849ec70f67ea10625, 2024)
- License: Unicode
Files extracted from upstream source:
@ -403,7 +403,7 @@ Files extracted 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
for instructions).
@ -413,7 +413,7 @@ Files generated from upstream source:
3. Reconfigure ICU with custom data config:
`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`
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

View File

@ -2,7 +2,7 @@ UNICODE LICENSE V3
COPYRIGHT AND PERMISSION NOTICE
Copyright © 2016-2023 Unicode, Inc.
Copyright © 2016-2024 Unicode, Inc.
NOTICE TO USER: Carefully read the following legal agreement. BY
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
authorization of the copyright holder.
SPDX-License-Identifier: Unicode-3.0
----------------------------------------------------------------------
Third-Party Software Licenses

View File

@ -114,13 +114,11 @@ UnhandledEngine::handleCharacter(UChar32 c) {
*/
ICULanguageBreakFactory::ICULanguageBreakFactory(UErrorCode &/*status*/) {
fEngines = 0;
fEngines = nullptr;
}
ICULanguageBreakFactory::~ICULanguageBreakFactory() {
if (fEngines != 0) {
delete fEngines;
}
}
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);
uprv_strcpy(lb_lw, "line");
UErrorCode kvStatus = U_ZERO_ERROR;
CharString value;
CharStringByteSink valueSink(&value);
loc.getKeywordValue("lb", valueSink, kvStatus);
auto value = loc.getKeywordValue<CharString>("lb", kvStatus);
if (U_SUCCESS(kvStatus) && (value == "strict" || value == "normal" || value == "loose")) {
uprv_strcat(lb_lw, "_");
uprv_strcat(lb_lw, value.data());
}
// lw=phrase is only supported in Japanese and Korean
if (uprv_strcmp(loc.getLanguage(), "ja") == 0 || uprv_strcmp(loc.getLanguage(), "ko") == 0) {
value.clear();
loc.getKeywordValue("lw", valueSink, kvStatus);
value = loc.getKeywordValue<CharString>("lw", kvStatus);
if (U_SUCCESS(kvStatus) && value == "phrase") {
uprv_strcat(lb_lw, "_");
uprv_strcat(lb_lw, value.data());
@ -500,7 +497,7 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status)
Locale
BreakIterator::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
if (type == ULOC_REQUESTED_LOCALE) {
return Locale(requestLocale);
return {requestLocale};
}
U_LOCALE_BASED(locBased, *this);
return locBased.getLocale(type, status);

View File

@ -7,18 +7,52 @@
#ifndef BYTESINKUTIL_H
#define BYTESINKUTIL_H
#include <type_traits>
#include "unicode/utypes.h"
#include "unicode/bytestream.h"
#include "unicode/edits.h"
#include "charstr.h"
#include "cmemory.h"
#include "uassert.h"
#include "ustr_imp.h"
U_NAMESPACE_BEGIN
class ByteSink;
class CharString;
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 {
public:
ByteSinkUtil() = delete; // all static
@ -57,32 +91,66 @@ public:
ByteSink &sink, uint32_t options, Edits *edits,
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:
static void appendNonEmptyUnchanged(const uint8_t *s, int32_t length,
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
#endif //BYTESINKUTIL_H

View File

@ -64,6 +64,7 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CanonicalIterator)
/**
*@param source string to get results for
*/
@ -73,10 +74,10 @@ CanonicalIterator::CanonicalIterator(const UnicodeString &sourceStr, UErrorCode
pieces_lengths(nullptr),
current(nullptr),
current_length(0),
nfd(*Normalizer2::getNFDInstance(status)),
nfcImpl(*Normalizer2Factory::getNFCImpl(status))
nfd(Normalizer2::getNFDInstance(status)),
nfcImpl(Normalizer2Factory::getNFCImpl(status))
{
if(U_SUCCESS(status) && nfcImpl.ensureCanonIterData(status)) {
if(U_SUCCESS(status) && nfcImpl->ensureCanonIterData(status)) {
setSource(sourceStr, status);
}
}
@ -172,7 +173,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
int32_t i = 0;
UnicodeString *list = nullptr;
nfd.normalize(newSource, source, status);
nfd->normalize(newSource, source, status);
if(U_FAILURE(status)) {
return;
}
@ -194,7 +195,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
current[0] = 0;
pieces[0] = new UnicodeString[1];
pieces_lengths[0] = 1;
if (pieces[0] == 0) {
if (pieces[0] == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
goto CleanPartialInitialization;
}
@ -203,7 +204,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
list = new UnicodeString[source.length()];
if (list == 0) {
if (list == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
goto CleanPartialInitialization;
}
@ -219,7 +220,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
// on the NFD form - see above).
for (; i < source.length(); i += U16_LENGTH(cp)) {
cp = source.char32At(i);
if (nfcImpl.isCanonSegmentStarter(cp)) {
if (nfcImpl->isCanonSegmentStarter(cp)) {
source.extract(start, i-start, list[list_length++]); // add up to i
start = i;
}
@ -252,9 +253,7 @@ void CanonicalIterator::setSource(const UnicodeString &newSource, UErrorCode &st
return;
// Common section to cleanup all local variables and reset object variables.
CleanPartialInitialization:
if (list != nullptr) {
delete[] list;
}
cleanPieces();
}
@ -264,10 +263,19 @@ CleanPartialInitialization:
* @param source the string to find permutations for
* @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)) {
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)));
int32_t i = 0;
@ -277,7 +285,7 @@ void U_EXPORT2 CanonicalIterator::permute(UnicodeString &source, UBool skipZeros
if (source.length() <= 2 && source.countChar32() <= 1) {
UnicodeString *toPut = new UnicodeString(source);
/* test for nullptr */
if (toPut == 0) {
if (toPut == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
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
//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 */
if(U_FAILURE(status)) {
return;
@ -346,7 +354,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i
Hashtable permutations(status);
Hashtable basic(status);
if (U_FAILURE(status)) {
return 0;
return nullptr;
}
result.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(*((UnicodeString *)(ne2->value.pointer)));
UnicodeString attempt;
nfd.normalize(possible, attempt, status);
nfd->normalize(possible, attempt, status);
// TODO: check if operator == is semanticaly the same as attempt.equals(segment)
if (attempt==segment) {
@ -399,7 +407,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i
/* Test for buffer overflows */
if(U_FAILURE(status)) {
return 0;
return nullptr;
}
// convert into a String[] to clean up storage
//String[] finalResult = new String[result.size()];
@ -407,7 +415,7 @@ UnicodeString* CanonicalIterator::getEquivalents(const UnicodeString &segment, i
int32_t resultCount;
if((resultCount = result.count()) != 0) {
finalResult = new UnicodeString[resultCount];
if (finalResult == 0) {
if (finalResult == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
@ -448,7 +456,7 @@ Hashtable *CanonicalIterator::getEquivalents2(Hashtable *fillinResult, const cha
for (int32_t i = 0; i < segLen; i += U16_LENGTH(cp)) {
// see if any character is at the start of some decomposition
U16_GET(segment, 0, i, segLen, cp);
if (!nfcImpl.getCanonStartSet(cp, starts)) {
if (!nfcImpl->getCanonStartSet(cp, starts)) {
continue;
}
// if so, see which decompositions match
@ -471,7 +479,7 @@ Hashtable *CanonicalIterator::getEquivalents2(Hashtable *fillinResult, const cha
UnicodeString item = *((UnicodeString *)(ne->value.pointer));
UnicodeString *toAdd = new UnicodeString(prefix);
/* test for nullptr */
if (toAdd == 0) {
if (toAdd == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
@ -509,7 +517,7 @@ Hashtable *CanonicalIterator::extract(Hashtable *fillinResult, UChar32 comp, con
UnicodeString temp(comp);
int32_t inputLen=temp.length();
UnicodeString decompString;
nfd.normalize(temp, decompString, status);
nfd->normalize(temp, decompString, status);
if (U_FAILURE(status)) {
return nullptr;
}
@ -573,7 +581,7 @@ Hashtable *CanonicalIterator::extract(Hashtable *fillinResult, UChar32 comp, con
// brute force approach
// check to make sure result is canonically equivalent
UnicodeString trial;
nfd.normalize(temp, trial, status);
nfd->normalize(temp, trial, status);
if(U_FAILURE(status) || trial.compare(segment+segmentPos, segLen - segmentPos) != 0) {
return nullptr;
}

View File

@ -104,6 +104,13 @@ public:
*/
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 {
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) {
delete this;
}
return 0;
return nullptr;
}
virtual ~SimpleFilteredSentenceBreakData();

View File

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

View File

@ -3,21 +3,21 @@
#include <utility>
#include "bytesinkutil.h" // CharStringByteSink
#include "bytesinkutil.h" // StringByteSink<CharString>
#include "charstr.h"
#include "cstring.h"
#include "ulocimp.h"
#include "unicode/localebuilder.h"
#include "unicode/locid.h"
U_NAMESPACE_BEGIN
namespace {
#define UPRV_ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
#define UPRV_ISALPHANUM(c) (uprv_isASCIILetter(c) || UPRV_ISDIGIT(c) )
inline bool UPRV_ISDIGIT(char c) { return c >= '0' && c <= '9'; }
inline bool UPRV_ISALPHANUM(char c) { return uprv_isASCIILetter(c) || UPRV_ISDIGIT(c); }
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)) {
case 'u':
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_(),
script_(), region_(), variant_(nullptr), extensions_(nullptr)
{
@ -68,8 +72,10 @@ LocaleBuilder& LocaleBuilder::setLanguageTag(StringPiece tag)
return *this;
}
static void setField(StringPiece input, char* dest, UErrorCode& errorCode,
UBool (*test)(const char*, int32_t)) {
namespace {
void setField(StringPiece input, char* dest, UErrorCode& errorCode,
bool (*test)(const char*, int32_t)) {
if (U_FAILURE(errorCode)) { return; }
if (input.empty()) {
dest[0] = '\0';
@ -81,6 +87,8 @@ static void setField(StringPiece input, char* dest, UErrorCode& errorCode,
}
}
} // namespace
LocaleBuilder& LocaleBuilder::setLanguage(StringPiece language)
{
setField(language, language_, status_, &ultag_isLanguageSubtag);
@ -99,7 +107,9 @@ LocaleBuilder& LocaleBuilder::setRegion(StringPiece region)
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++) {
if (*data == '_') {
*data = '-';
@ -109,6 +119,8 @@ static void transform(char* data, int32_t len) {
}
}
} // namespace
LocaleBuilder& LocaleBuilder::setVariant(StringPiece variant)
{
if (U_FAILURE(status_)) { return *this; }
@ -134,7 +146,9 @@ LocaleBuilder& LocaleBuilder::setVariant(StringPiece variant)
return *this;
}
static bool
namespace {
bool
_isKeywordValue(const char* key, const char* value, int32_t value_len)
{
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);
}
static void
void
_copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
Locale& to, bool validate, UErrorCode& errorCode)
{
@ -169,9 +183,7 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
}
const char* key;
while ((key = keywords->next(nullptr, errorCode)) != nullptr) {
CharString value;
CharStringByteSink sink(&value);
from.getKeywordValue(key, sink, errorCode);
auto value = from.getKeywordValue<CharString>(key, errorCode);
if (U_FAILURE(errorCode)) { return; }
if (uprv_strcmp(key, kAttributeKey) == 0) {
transform(value.data(), value.length());
@ -186,9 +198,10 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
}
}
void static
void
_clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
{
if (U_FAILURE(errorCode)) { return; }
// Clear Unicode attributes
locale.setKeywordValue(kAttributeKey, "", errorCode);
@ -201,9 +214,10 @@ _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
}
}
static void
void
_setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& errorCode)
{
if (U_FAILURE(errorCode)) { return; }
// Add the unicode extensions to extensions_
CharString locale_str("und-u-", errorCode);
locale_str.append(value, errorCode);
@ -212,6 +226,8 @@ _setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& error
locale, false, errorCode);
}
} // namespace
LocaleBuilder& LocaleBuilder::setExtension(char key, StringPiece value)
{
if (U_FAILURE(status_)) { return *this; }
@ -289,10 +305,8 @@ LocaleBuilder& LocaleBuilder::addUnicodeLocaleAttribute(
return *this;
}
CharString attributes;
CharStringByteSink sink(&attributes);
UErrorCode localErrorCode = U_ZERO_ERROR;
extensions_->getKeywordValue(kAttributeKey, sink, localErrorCode);
auto attributes = extensions_->getKeywordValue<CharString>(kAttributeKey, localErrorCode);
if (U_FAILURE(localErrorCode)) {
CharString new_attributes(value_str.data(), status_);
// No attributes, set the attribute.
@ -344,9 +358,7 @@ LocaleBuilder& LocaleBuilder::removeUnicodeLocaleAttribute(
}
if (extensions_ == nullptr) { return *this; }
UErrorCode localErrorCode = U_ZERO_ERROR;
CharString attributes;
CharStringByteSink sink(&attributes);
extensions_->getKeywordValue(kAttributeKey, sink, localErrorCode);
auto attributes = extensions_->getKeywordValue<CharString>(kAttributeKey, localErrorCode);
// get failure, just return
if (U_FAILURE(localErrorCode)) { return *this; }
// 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
// created: 2019may08 Markus W. Scherer
#include <optional>
#include "unicode/utypes.h"
#include "unicode/localebuilder.h"
#include "unicode/localematcher.h"
@ -302,7 +304,7 @@ LocaleMatcher LocaleMatcher::Builder::build(UErrorCode &errorCode) const {
namespace {
LSR getMaximalLsrOrUnd(const XLikelySubtags &likelySubtags, const Locale &locale,
LSR getMaximalLsrOrUnd(const LikelySubtags &likelySubtags, const Locale &locale,
UErrorCode &errorCode) {
if (U_FAILURE(errorCode) || locale.isBogus() || *locale.getName() == 0 /* "und" */) {
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) :
likelySubtags(*XLikelySubtags::getSingleton(errorCode)),
likelySubtags(*LikelySubtags::getSingleton(errorCode)),
localeDistance(*LocaleDistance::getSingleton(errorCode)),
thresholdDistance(builder.thresholdDistance_),
demotionPerDesiredLocale(0),
@ -551,7 +553,7 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) noexcept {
class LocaleLsrIterator {
public:
LocaleLsrIterator(const XLikelySubtags &likelySubtags, Locale::Iterator &locales,
LocaleLsrIterator(const LikelySubtags &likelySubtags, Locale::Iterator &locales,
ULocMatchLifetime lifetime) :
likelySubtags(likelySubtags), locales(locales), lifetime(lifetime) {}
@ -596,7 +598,7 @@ public:
}
private:
const XLikelySubtags &likelySubtags;
const LikelySubtags &likelySubtags;
Locale::Iterator &locales;
ULocMatchLifetime lifetime;
const Locale *current = nullptr, *remembered = nullptr;
@ -605,10 +607,11 @@ private:
const Locale *LocaleMatcher::getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return nullptr; }
int32_t suppIndex = getBestSuppIndex(
std::optional<int32_t> suppIndex = getBestSuppIndex(
getMaximalLsrOrUnd(likelySubtags, desiredLocale, 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,
@ -618,12 +621,14 @@ const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales,
return defaultLocale;
}
LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES);
int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale;
std::optional<int32_t> suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
return U_SUCCESS(errorCode) && suppIndex.has_value() ? supportedLocales[*suppIndex]
: defaultLocale;
}
const Locale *LocaleMatcher::getBestMatchForListString(
StringPiece desiredLocaleList, UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return nullptr; }
LocalePriorityList list(desiredLocaleList, errorCode);
LocalePriorityList::Iterator iter = list.iterator();
return getBestMatch(iter, errorCode);
@ -634,13 +639,13 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult(
if (U_FAILURE(errorCode)) {
return Result(nullptr, defaultLocale, -1, -1, false);
}
int32_t suppIndex = getBestSuppIndex(
std::optional<int32_t> suppIndex = getBestSuppIndex(
getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode),
nullptr, errorCode);
if (U_FAILURE(errorCode) || suppIndex < 0) {
if (U_FAILURE(errorCode) || !suppIndex.has_value()) {
return Result(nullptr, defaultLocale, -1, -1, false);
} 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);
}
LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES);
int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
if (U_FAILURE(errorCode) || suppIndex < 0) {
std::optional<int32_t> suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
if (U_FAILURE(errorCode) || !suppIndex.has_value()) {
return Result(nullptr, defaultLocale, -1, -1, false);
} else {
return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex],
lsrIter.getBestDesiredIndex(), suppIndex, true);
return Result(lsrIter.orphanRemembered(), supportedLocales[*suppIndex],
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 {
if (U_FAILURE(errorCode)) { return -1; }
if (U_FAILURE(errorCode)) { return std::nullopt; }
int32_t desiredIndex = 0;
int32_t bestSupportedLsrIndex = -1;
for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(thresholdDistance);;) {
@ -684,7 +690,7 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai
bestShiftedDistance = LocaleDistance::getShiftedDistance(bestIndexAndDistance);
if (remainingIter != nullptr) {
remainingIter->rememberCurrent(desiredIndex, errorCode);
if (U_FAILURE(errorCode)) { return -1; }
if (U_FAILURE(errorCode)) { return std::nullopt; }
}
bestSupportedLsrIndex = LocaleDistance::getIndex(bestIndexAndDistance);
}
@ -695,20 +701,21 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai
break;
}
desiredLSR = remainingIter->next(errorCode);
if (U_FAILURE(errorCode)) { return -1; }
if (U_FAILURE(errorCode)) { return std::nullopt; }
++desiredIndex;
}
if (bestSupportedLsrIndex < 0) {
// no good match
return -1;
return std::nullopt;
}
return supportedIndexes[bestSupportedLsrIndex];
}
UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported,
UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return false; }
LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode);
if (U_FAILURE(errorCode)) { return 0; }
if (U_FAILURE(errorCode)) { return false; }
const LSR *pSuppLSR = &suppLSR;
int32_t indexAndDistance = localeDistance.getBestIndexAndDistance(
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 {
if (U_FAILURE(errorCode)) { return 0.; }
// Returns the inverse of the distance: That is, 1-distance(desired, supported).
LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode);
if (U_FAILURE(errorCode)) { return 0; }
if (U_FAILURE(errorCode)) { return 0.; }
const LSR *pSuppLSR = &suppLSR;
int32_t indexAndDistance = localeDistance.getBestIndexAndDistance(
getMaximalLsrOrUnd(likelySubtags, desired, errorCode),

View File

@ -21,13 +21,13 @@ U_NAMESPACE_BEGIN
namespace {
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();
}
UBool compareLocales(const UHashTok t1, const UHashTok t2) {
auto *l1 = static_cast<const Locale *>(t1.pointer);
auto *l2 = static_cast<const Locale *>(t2.pointer);
const auto* l1 = static_cast<const Locale*>(t1.pointer);
const auto* l2 = static_cast<const Locale*>(t2.pointer);
return *l1 == *l2;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -62,7 +62,7 @@ public:
ULocMatchFavorSubtag favorSubtag,
ULocMatchDirection direction) const;
UBool isParadigmLSR(const LSR &lsr) const;
bool isParadigmLSR(const LSR &lsr) const;
int32_t getDefaultScriptDistance() const {
return defaultScriptDistance;
@ -83,13 +83,13 @@ private:
// tic constexpr int32_t MAX_INDEX = 0x1fffff; // avoids sign bit
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 &operator=(const LocaleDistance &other) = delete;
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 {
const LSR *pSupp = &supported;
return getBestIndexAndDistance(
@ -119,7 +119,7 @@ private:
return defaultRegionDistance;
}
const XLikelySubtags &likelySubtags;
const LikelySubtags &likelySubtags;
// 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.

View File

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

View File

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

View File

@ -19,6 +19,8 @@
* that then do not depend on resource bundle code and likely-subtags data.
*/
#include <utility>
#include "unicode/bytestream.h"
#include "unicode/utypes.h"
#include "unicode/locid.h"
@ -33,72 +35,31 @@
#include "cstring.h"
#include "loclikelysubtags.h"
#include "ulocimp.h"
#include "ustr_imp.h"
/**
* 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;
}
namespace {
/**
* 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
* 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
* 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 langLength The length of the language tag.
* @param script The script tag to use.
* @param scriptLength The length of the script tag.
* @param region The region tag to use.
* @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 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 err A pointer to a UErrorCode for error reporting.
**/
static void U_CALLCONV
void U_CALLCONV
createTagStringWithAlternates(
const char* lang,
int32_t langLength,
@ -106,392 +67,125 @@ createTagStringWithAlternates(
int32_t scriptLength,
const char* region,
int32_t regionLength,
const char* variant,
int32_t variantLength,
const char* trailing,
int32_t trailingLength,
const char* alternateTags,
icu::ByteSink& sink,
UErrorCode* err) {
if (U_FAILURE(*err)) {
goto error;
UErrorCode& err) {
if (U_FAILURE(err)) {
return;
}
else if (langLength >= ULOC_LANG_CAPACITY ||
if (langLength >= ULOC_LANG_CAPACITY ||
scriptLength >= ULOC_SCRIPT_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) {
appendTag(
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);
}
sink.Append(lang, langLength);
}
if (scriptLength > 0) {
appendTag(
script,
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);
}
sink.Append("_", 1);
sink.Append(script, scriptLength);
}
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);
if (!regionAppended) {
sink.Append(region, regionLength);
}
if (variantLength > 0) {
if (regionLength == 0) {
/* extra separator is required */
sink.Append("_", 1);
}
sink.Append("_", 1);
sink.Append(variant, variantLength);
}
if (trailingLength > 0) {
/*
* Copy the trailing data into the supplied buffer.
*/
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;
}
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) {
goto error;
err = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
trailingIndex = parseTagString(
localeID,
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;
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;
}
goto error;
}
if (langLength > 3) {
goto error;
if (!CHECK_TRAILING_VARIANT_SIZE(variant.data(), variant.length())) {
err = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
/* Find the length of the trailing portion. */
while (_isIDSeparator(localeID[trailingIndex])) {
trailingIndex++;
if (lang.length() == 4) {
if (script.isEmpty()) {
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);
{
const icu::XLikelySubtags* likelySubtags = icu::XLikelySubtags::getSingleton(*err);
if(U_FAILURE(*err)) {
goto error;
int32_t trailingLength = (int32_t)uprv_strlen(trailing);
const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err);
if (U_FAILURE(err)) {
return;
}
// We need to keep l on the stack because lsr may point into internal
// memory of l.
icu::Locale l = icu::Locale::createFromName(localeID);
if (l.isBogus()) {
goto error;
err = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, *err);
if(U_FAILURE(*err)) {
goto error;
icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, err);
if (U_FAILURE(err)) {
return;
}
const char* language = lsr.language;
if (uprv_strcmp(language, "und") == 0) {
@ -504,97 +198,57 @@ _uloc_addLikelySubtags(const char* localeID,
(int32_t)uprv_strlen(lsr.script),
lsr.region,
(int32_t)uprv_strlen(lsr.region),
variant.data(),
variant.length(),
trailing,
trailingLength,
nullptr,
sink,
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
// 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
void
_uloc_minimizeSubtags(const char* localeID,
icu::ByteSink& sink,
bool favorScript,
UErrorCode* err) {
icu::CharString maximizedTagBuffer;
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;
UErrorCode& err) {
if (U_FAILURE(err)) {
return;
}
trailingIndex =
parseTagString(
localeID,
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;
if (localeID == nullptr) {
err = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
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. */
while (_isIDSeparator(localeID[trailingIndex])) {
trailingIndex++;
if (!CHECK_TRAILING_VARIANT_SIZE(variant.data(), variant.length())) {
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);
if(U_FAILURE(*err)) {
goto error;
const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err);
if (U_FAILURE(err)) {
return;
}
icu::LSR lsr = likelySubtags->minimizeSubtags(
{lang, langLength},
{script, scriptLength},
{region, regionLength},
lang.toStringPiece(),
script.toStringPiece(),
region.toStringPiece(),
favorScript,
*err);
if(U_FAILURE(*err)) {
goto error;
err);
if (U_FAILURE(err)) {
return;
}
const char* language = lsr.language;
if (uprv_strcmp(language, "und") == 0) {
@ -607,74 +261,46 @@ _uloc_minimizeSubtags(const char* localeID,
(int32_t)uprv_strlen(lsr.script),
lsr.region,
(int32_t)uprv_strlen(lsr.region),
variant.data(),
variant.length(),
trailing,
trailingLength,
nullptr,
sink,
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
uloc_addLikelySubtags(const char* localeID,
char* maximizedLocaleID,
int32_t maximizedLocaleIDCapacity,
UErrorCode* status) {
if (U_FAILURE(*status)) {
return 0;
}
icu::CheckedArrayByteSink sink(
maximizedLocaleID, maximizedLocaleIDCapacity);
return icu::ByteSinkUtil::viaByteSinkToTerminatedChars(
maximizedLocaleID, maximizedLocaleIDCapacity,
[&](icu::ByteSink& sink, UErrorCode& status) {
ulocimp_addLikelySubtags(localeID, sink, status);
int32_t reslen = sink.NumberOfBytesAppended();
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;
},
*status);
}
static UBool
_ulocimp_addLikelySubtags(const char* localeID,
icu::ByteSink& sink,
UErrorCode* status) {
icu::CharString localeBuffer;
{
icu::CharStringByteSink localeSink(&localeBuffer);
ulocimp_canonicalize(localeID, localeSink, status);
}
if (U_SUCCESS(*status)) {
return _uloc_addLikelySubtags(localeBuffer.data(), sink, status);
} else {
return false;
}
U_EXPORT icu::CharString
ulocimp_addLikelySubtags(const char* localeID,
UErrorCode& status) {
return icu::ByteSinkUtil::viaByteSinkToCharString(
[&](icu::ByteSink& sink, UErrorCode& status) {
ulocimp_addLikelySubtags(localeID, sink, status);
},
status);
}
U_CAPI void U_EXPORT2
U_EXPORT void
ulocimp_addLikelySubtags(const char* localeID,
icu::ByteSink& sink,
UErrorCode* status) {
_ulocimp_addLikelySubtags(localeID, sink, status);
UErrorCode& 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
@ -682,40 +308,32 @@ uloc_minimizeSubtags(const char* localeID,
char* minimizedLocaleID,
int32_t minimizedLocaleIDCapacity,
UErrorCode* status) {
if (U_FAILURE(*status)) {
return 0;
}
icu::CheckedArrayByteSink sink(
minimizedLocaleID, minimizedLocaleIDCapacity);
return icu::ByteSinkUtil::viaByteSinkToTerminatedChars(
minimizedLocaleID, minimizedLocaleIDCapacity,
[&](icu::ByteSink& sink, UErrorCode& status) {
ulocimp_minimizeSubtags(localeID, sink, false, status);
int32_t reslen = sink.NumberOfBytesAppended();
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;
},
*status);
}
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,
icu::ByteSink& sink,
bool favorScript,
UErrorCode* status) {
icu::CharString localeBuffer;
{
icu::CharStringByteSink localeSink(&localeBuffer);
ulocimp_canonicalize(localeID, localeSink, status);
}
UErrorCode& status) {
if (U_FAILURE(status)) { return; }
icu::CharString localeBuffer = ulocimp_canonicalize(localeID, status);
_uloc_minimizeSubtags(localeBuffer.data(), sink, favorScript, status);
}
@ -728,22 +346,16 @@ static const char LANG_DIR_STRING[] =
U_CAPI UBool U_EXPORT2
uloc_isRightToLeft(const char *locale) {
UErrorCode errorCode = U_ZERO_ERROR;
char script[8];
int32_t scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &errorCode);
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING ||
scriptLength == 0) {
icu::CharString lang;
icu::CharString script;
ulocimp_getSubtags(locale, &lang, &script, nullptr, nullptr, nullptr, errorCode);
if (U_FAILURE(errorCode) || script.isEmpty()) {
// Fastpath: We know the likely scripts and their writing direction
// for some common languages.
errorCode = U_ZERO_ERROR;
char lang[8];
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 (!lang.isEmpty()) {
const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang.data());
if (langPtr != nullptr) {
switch (langPtr[langLength]) {
switch (langPtr[lang.length()]) {
case '-': return false;
case '+': return true;
default: break; // partial match of a longer code
@ -752,21 +364,16 @@ uloc_isRightToLeft(const char *locale) {
}
// Otherwise, find the likely script.
errorCode = U_ZERO_ERROR;
icu::CharString likely;
{
icu::CharStringByteSink sink(&likely);
ulocimp_addLikelySubtags(locale, sink, &errorCode);
}
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
icu::CharString likely = ulocimp_addLikelySubtags(locale, errorCode);
if (U_FAILURE(errorCode)) {
return false;
}
scriptLength = uloc_getScript(likely.data(), script, UPRV_LENGTHOF(script), &errorCode);
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING ||
scriptLength == 0) {
ulocimp_getSubtags(likely.data(), nullptr, &script, nullptr, nullptr, nullptr, errorCode);
if (U_FAILURE(errorCode) || script.isEmpty()) {
return false;
}
}
UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script);
UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script.data());
return uscript_isRightToLeft(scriptCode);
}
@ -779,65 +386,52 @@ Locale::isRightToLeft() const {
U_NAMESPACE_END
// The following must at least allow for rg key value (6) plus terminator (1).
#define ULOC_RG_BUFLEN 8
namespace {
icu::CharString
GetRegionFromKey(const char* localeID, const char* key, UErrorCode& status) {
icu::CharString result;
U_CAPI int32_t U_EXPORT2
ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
char *region, int32_t regionCapacity, UErrorCode* status) {
if (U_FAILURE(*status)) {
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 {
// First check for keyword value
icu::CharString kw = ulocimp_getKeywordValue(localeID, key, status);
int32_t len = kw.length();
if (U_SUCCESS(status) && len >= 3 && len <= 7) {
// 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])) {
rgLen = 2;
rgBuf[0] = uprv_toupper(data[0]);
rgBuf[1] = uprv_toupper(data[1]);
result.append(uprv_toupper(data[0]), status);
result.append(uprv_toupper(data[1]), status);
} else {
// assume three-digit region code
rgLen = 3;
uprv_memcpy(rgBuf, data, rgLen);
result.append(data, 3, status);
}
}
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);
return result;
}
} // 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;
}
// TODO(ICU-20777): Rename to just LikelySubtagsData.
struct XLikelySubtagsData {
struct LikelySubtagsData {
UResourceBundle *langInfoBundle = nullptr;
UniqueCharStrings strings;
CharStringMap languageAliases;
@ -63,14 +62,15 @@ struct XLikelySubtagsData {
LocaleDistanceData distanceData;
XLikelySubtagsData(UErrorCode &errorCode) : strings(errorCode) {}
LikelySubtagsData(UErrorCode &errorCode) : strings(errorCode) {}
~XLikelySubtagsData() {
~LikelySubtagsData() {
ures_close(langInfoBundle);
delete[] lsrs;
}
void load(UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return; }
langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode);
if (U_FAILURE(errorCode)) { return; }
StackUResourceBundle stackTempBundle;
@ -231,6 +231,7 @@ struct XLikelySubtagsData {
private:
bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value,
LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return false; }
if (table.findValue(key, value)) {
ResourceArray stringArray = value.getArray(errorCode);
if (U_FAILURE(errorCode)) { return false; }
@ -297,7 +298,7 @@ private:
}
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("");
}
encoded &= 0x00ffffff;
@ -315,6 +316,7 @@ private:
bool readLSREncodedStrings(const ResourceTable &table, const char* key, ResourceValue &value, const ResourceArray& m49Array,
LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return false; }
if (table.findValue(key, value)) {
const int32_t* vectors = value.getIntVector(length, errorCode);
if (U_FAILURE(errorCode)) { return false; }
@ -339,7 +341,7 @@ private:
namespace {
XLikelySubtags *gLikelySubtags = nullptr;
LikelySubtags *gLikelySubtags = nullptr;
UVector *gMacroregions = nullptr;
UInitOnce gInitOnce {};
@ -352,21 +354,36 @@ UBool U_CALLCONV cleanup() {
return true;
}
static const char16_t RANGE_MARKER = 0x7E; /* '~' */
UVector* loadMacroregions(UErrorCode &status) {
LocalPointer<UVector> newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status);
constexpr const char16_t* MACROREGION_HARDCODE[] = {
u"001~3",
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));
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 (U_SUCCESS(status) && ures_hasNext(regionMacro.getAlias())) {
UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),nullptr,&status);
constexpr char16_t RANGE_MARKER = 0x7E; /* '~' */
void processMacroregionRange(const UnicodeString& regionName, UVector* newMacroRegions, UErrorCode& status) {
if (U_FAILURE(status)) { return; }
int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER);
char16_t buf[6];
regionName.extract(buf,6,status);
@ -382,20 +399,68 @@ UVector* loadMacroregions(UErrorCode &status) {
LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), 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();
}
} // namespace
void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) {
void U_CALLCONV LikelySubtags::initLikelySubtags(UErrorCode &errorCode) {
// This function is invoked only via umtx_initOnce().
U_ASSERT(gLikelySubtags == nullptr);
XLikelySubtagsData data(errorCode);
LikelySubtagsData data(errorCode);
data.load(errorCode);
if (U_FAILURE(errorCode)) { return; }
gLikelySubtags = new XLikelySubtags(data);
gMacroregions = loadMacroregions(errorCode);
gLikelySubtags = new LikelySubtags(data);
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) {
delete gLikelySubtags;
delete gMacroregions;
@ -406,13 +471,13 @@ void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) {
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; }
umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode);
umtx_initOnce(gInitOnce, &LikelySubtags::initLikelySubtags, errorCode);
return gLikelySubtags;
}
XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) :
LikelySubtags::LikelySubtags(LikelySubtagsData &data) :
langInfoBundle(data.langInfoBundle),
strings(data.strings.orphanCharStrings()),
languageAliases(std::move(data.languageAliases)),
@ -421,7 +486,7 @@ XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) :
lsrs(data.lsrs),
#if U_DEBUG
lsrsLength(data.lsrsLength),
#endif
#endif // U_DEBUG
distanceData(std::move(data.distanceData)) {
data.langInfoBundle = nullptr;
data.lsrs = nullptr;
@ -447,18 +512,19 @@ XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) :
}
}
XLikelySubtags::~XLikelySubtags() {
LikelySubtags::~LikelySubtags() {
ures_close(langInfoBundle);
delete strings;
delete[] lsrs;
}
LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale,
LSR LikelySubtags::makeMaximizedLsrFrom(const Locale &locale,
bool returnInputIfUnmatch,
UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
if (locale.isBogus()) {
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
return LSR("", "", "", LSR::EXPLICIT_LSR);
return {};
}
const char *name = locale.getName();
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
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,
bool returnInputIfUnmatch,
UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
// Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK.
// They should match only themselves,
// 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) {
switch (c1) {
case 'A':
if (returnInputIfUnmatch) {
return LSR(language, script, region, LSR::EXPLICIT_LSR);
}
return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region,
LSR::EXPLICIT_LSR, errorCode);
case 'B':
if (returnInputIfUnmatch) {
return LSR(language, script, region, LSR::EXPLICIT_LSR);
}
return LSR(PSEUDO_BIDI_PREFIX, language, script, region,
LSR::EXPLICIT_LSR, errorCode);
case 'C':
if (returnInputIfUnmatch) {
return LSR(language, script, region, LSR::EXPLICIT_LSR);
}
return LSR(PSEUDO_CRACKED_PREFIX, language, script, region,
LSR::EXPLICIT_LSR, errorCode);
default: // normal locale
@ -536,9 +612,10 @@ LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, c
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,
UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
return maximize({language, (int32_t)uprv_strlen(language)},
{script, (int32_t)uprv_strlen(script)},
{region, (int32_t)uprv_strlen(region)},
@ -546,23 +623,21 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha
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,
// we read the same data used by Region into gMacroregions avoid dependency
// from common to i18n/region.cpp
if (U_FAILURE(errorCode)) { return false; }
umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode);
umtx_initOnce(gInitOnce, &LikelySubtags::initLikelySubtags, errorCode);
if (U_FAILURE(errorCode)) { return false; }
UnicodeString str(UnicodeString::fromUTF8(region));
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,
UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) {
return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode);
}
if (U_FAILURE(errorCode)) { return {}; }
if (language.compare("und") == 0) {
language = "";
}
@ -681,7 +756,7 @@ LSR XLikelySubtags::maximize(StringPiece language, StringPiece script, StringPie
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:
// likelyInfo bit 1 is set if the previous comparison with lsr
// 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().
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) {
language = "";
}
@ -781,7 +856,7 @@ int32_t XLikelySubtags::getLikelyIndex(const char *language, const char *script)
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;
uint8_t c;
if ((c = s[i]) == 0) {
@ -814,7 +889,7 @@ int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) {
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;
uint8_t c;
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,
bool favorScript,
UErrorCode &errorCode) const {
if (U_FAILURE(errorCode)) { return {}; }
LSR max = maximize(language, script, region, true, errorCode);
if (U_FAILURE(errorCode)) {
return max;
}
if (U_FAILURE(errorCode)) { return {}; }
// If no match, return it.
if (uprv_strlen(max.language) == 0 &&
uprv_strlen(max.script) == 0 &&
@ -868,9 +942,7 @@ LSR XLikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
}
// try language
LSR test = maximize(max.language, "", "", true, errorCode);
if (U_FAILURE(errorCode)) {
return max;
}
if (U_FAILURE(errorCode)) { return {}; }
if (test.isEquivalentTo(max)) {
return LSR(max.language, "", "", LSR::DONT_CARE_FLAGS, errorCode);
}
@ -879,27 +951,21 @@ LSR XLikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
// favor Region
// try language and region
test = maximize(max.language, "", max.region, true, errorCode);
if (U_FAILURE(errorCode)) {
return max;
}
if (U_FAILURE(errorCode)) { return {}; }
if (test.isEquivalentTo(max)) {
return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode);
}
}
// try language and script
test = maximize(max.language, max.script, "", true, errorCode);
if (U_FAILURE(errorCode)) {
return max;
}
if (U_FAILURE(errorCode)) { return {}; }
if (test.isEquivalentTo(max)) {
return LSR(max.language, max.script, "", LSR::DONT_CARE_FLAGS, errorCode);
}
if (favorScript) {
// try language and region
test = maximize(max.language, "", max.region, true, errorCode);
if (U_FAILURE(errorCode)) {
return max;
}
if (U_FAILURE(errorCode)) { return {}; }
if (test.isEquivalentTo(max)) {
return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode);
}

View File

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

View File

@ -28,7 +28,6 @@
*/
#include "locmap.h"
#include "bytesinkutil.h"
#include "charstr.h"
#include "cstring.h"
#include "cmemory.h"
@ -49,6 +48,8 @@
* [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'
*/
#define ILCID_POSIX_ELEMENT_ARRAY(hostID, languageID, posixID) \
static const ILcidPosixElement locmap_ ## languageID [] = { \
constexpr ILcidPosixElement locmap_ ## languageID [] = { \
{LANGUAGE_LCID(hostID), #languageID}, /* parent locale */ \
{hostID, #posixID}, \
};
@ -97,7 +98,7 @@ static const ILcidPosixElement locmap_ ## languageID [] = { \
* @param id the POSIX ID, either a language or language_TERRITORY
*/
#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)
/* 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(am), /* am Amharic 0x5e */
ILCID_POSIX_MAP(ar), /* ar Arabic 0x01 */
@ -945,14 +946,14 @@ static const ILcidPosixMap gPosixIDmap[] = {
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.
* The function is not private because this struct must stay as a C struct,
* and this is an internal class.
*/
static int32_t
int32_t
idCmp(const char* id1, const char* id2)
{
int32_t diffIdx = 0;
@ -972,9 +973,10 @@ idCmp(const char* id1, const char* id2)
* no equivalent Windows LCID.
* @return the LCID
*/
static uint32_t
getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode* status)
uint32_t
getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status)
{
if (U_FAILURE(status)) { return locmap_root->hostID; }
int32_t bestIdx = 0;
int32_t bestIdxDiff = 0;
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] == '@')
&& this_0->regionMaps[bestIdx].posixID[bestIdxDiff] == 0)
{
*status = U_USING_FALLBACK_WARNING;
status = U_USING_FALLBACK_WARNING;
return this_0->regionMaps[bestIdx].hostID;
}
/*no match found */
*status = U_ILLEGAL_ARGUMENT_ERROR;
return this_0->regionMaps->hostID;
status = U_ILLEGAL_ARGUMENT_ERROR;
return locmap_root->hostID;
}
static const char*
const char*
getPosixID(const ILcidPosixMap *this_0, uint32_t hostID)
{
uint32_t i;
@ -1035,19 +1037,21 @@ getPosixID(const ILcidPosixMap *this_0, uint32_t hostID)
* quz -> qu
* prs -> fa
*/
#define FIX_LANGUAGE_ID_TAG(buffer, len) \
if (len >= 3) { \
if (buffer[0] == 'q' && buffer[1] == 'u' && buffer[2] == 'z') {\
buffer[2] = 0; \
uprv_strcat(buffer, buffer+3); \
} else if (buffer[0] == 'p' && buffer[1] == 'r' && buffer[2] == 's') {\
buffer[0] = 'f'; buffer[1] = 'a'; buffer[2] = 0; \
uprv_strcat(buffer, buffer+3); \
} \
void FIX_LANGUAGE_ID_TAG(char* buffer, int32_t len) {
if (len >= 3) {
if (buffer[0] == 'q' && buffer[1] == 'u' && buffer[2] == 'z') {
buffer[2] = 0;
uprv_strcat(buffer, buffer+3);
} else if (buffer[0] == 'p' && buffer[1] == 'r' && buffer[2] == 's') {
buffer[0] = 'f'; buffer[1] = 'a'; buffer[2] = 0;
uprv_strcat(buffer, buffer+3);
}
}
}
#endif
} // namespace
U_CAPI int32_t
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 */
*status = U_ILLEGAL_ARGUMENT_ERROR;
return -1;
return 0;
}
/*
@ -1176,11 +1180,7 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status)
// Check any for keywords.
if (uprv_strchr(localeID, '@'))
{
icu::CharString collVal;
{
icu::CharStringByteSink sink(&collVal);
ulocimp_getKeywordValue(localeID, "collation", sink, status);
}
icu::CharString collVal = ulocimp_getKeywordValue(localeID, "collation", *status);
if (U_SUCCESS(*status) && !collVal.isEmpty())
{
// 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
{
// If the locale ID contains keywords other than collation, just use the base name.
{
icu::CharStringByteSink sink(&baseName);
ulocimp_getBaseName(localeID, sink, status);
}
baseName = ulocimp_getBaseName(localeID, *status);
if (U_SUCCESS(*status) && !baseName.isEmpty())
{
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
icu::CharString asciiBCP47Tag;
{
icu::CharStringByteSink sink(&asciiBCP47Tag);
ulocimp_toLanguageTag(mylocaleID, sink, false, status);
}
icu::CharString asciiBCP47Tag = ulocimp_toLanguageTag(mylocaleID, false, *status);
if (U_SUCCESS(*status))
{
@ -1253,6 +1246,14 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status)
U_CAPI uint32_t
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,
// or for locales that don't follow patterns the platform expects.
uint32_t low = 0;
@ -1266,11 +1267,6 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
UErrorCode myStatus;
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 */
while (high > low) /*binary search*/{
@ -1288,7 +1284,7 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
low = mid;
}
else /*we found it*/{
return getHostID(&gPosixIDmap[mid], posixID, status);
return getHostID(&gPosixIDmap[mid], posixID, *status);
}
oldmid = mid;
}
@ -1299,7 +1295,7 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
*/
for (idx = 0; idx < gLocaleCount; idx++ ) {
myStatus = U_ZERO_ERROR;
value = getHostID(&gPosixIDmap[idx], posixID, &myStatus);
value = getHostID(&gPosixIDmap[idx], posixID, myStatus);
if (myStatus == U_ZERO_ERROR) {
return value;
}
@ -1315,5 +1311,5 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
/* no match found */
*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/uloc.h"
#include "unicode/ures.h"
#include "bytesinkutil.h"
#include "charstr.h"
#include "cstring.h"
#include "ulocimp.h"
@ -50,10 +49,10 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
int32_t *pLength,
UErrorCode *pErrorCode)
{
if (U_FAILURE(*pErrorCode)) { return nullptr; }
/* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/
const char16_t *item=nullptr;
UErrorCode errorCode;
char explicitFallbackName[ULOC_FULLNAME_CAPACITY] = {0};
/*
* open the bundle for the current locale
@ -129,14 +128,15 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
break;
}
u_UCharsToChars(fallbackLocale, explicitFallbackName, len);
icu::CharString explicitFallbackName;
explicitFallbackName.appendInvariantChars(fallbackLocale, len, errorCode);
/* guard against recursive fallback */
if(uprv_strcmp(explicitFallbackName, locale)==0){
if (explicitFallbackName == locale) {
*pErrorCode = U_INTERNAL_PROGRAM_ERROR;
break;
}
rb.adoptInstead(ures_open(path, explicitFallbackName, &errorCode));
rb.adoptInstead(ures_open(path, explicitFallbackName.data(), &errorCode));
if(U_FAILURE(errorCode)){
*pErrorCode = errorCode;
break;
@ -150,21 +150,21 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
return item;
}
static ULayoutType
namespace {
ULayoutType
_uloc_getOrientationHelper(const char* localeId,
const char* key,
UErrorCode *status)
UErrorCode& status)
{
ULayoutType result = ULOC_LAYOUT_UNKNOWN;
if (!U_FAILURE(*status)) {
icu::CharString localeBuffer;
{
icu::CharStringByteSink sink(&localeBuffer);
ulocimp_canonicalize(localeId, sink, status);
}
if (U_FAILURE(status)) { return result; }
icu::CharString localeBuffer = ulocimp_canonicalize(localeId, status);
if (U_FAILURE(status)) { return result; }
if (!U_FAILURE(*status)) {
int32_t length = 0;
const char16_t* const value =
uloc_getTableStringWithFallback(
@ -174,9 +174,11 @@ _uloc_getOrientationHelper(const char* localeId,
nullptr,
key,
&length,
status);
&status);
if (!U_FAILURE(*status) && length != 0) {
if (U_FAILURE(status)) { return result; }
if (length != 0) {
switch(value[0])
{
case 0x0062: /* 'b' */
@ -192,21 +194,21 @@ _uloc_getOrientationHelper(const char* localeId,
result = ULOC_LAYOUT_TTB;
break;
default:
*status = U_INTERNAL_PROGRAM_ERROR;
status = U_INTERNAL_PROGRAM_ERROR;
break;
}
}
}
}
return result;
}
} // namespace
U_CAPI ULayoutType U_EXPORT2
uloc_getCharacterOrientation(const char* localeId,
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,
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&
LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
{
enum { BUFLEN = 128 }; // larger than ever needed
if (id.isBogus() || id.length() >= BUFLEN) {
if (id.isBogus()) {
result.setToBogus();
} else {
/*
@ -168,24 +166,29 @@ LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
*
* There should be only at most one '@' in a locale ID.
*/
char buffer[BUFLEN];
CharString buffer;
int32_t prev, i;
prev = 0;
for(;;) {
UErrorCode status = U_ZERO_ERROR;
do {
i = id.indexOf((char16_t)0x40, prev);
if(i < 0) {
// 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
} else {
// 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]
buffer[i] = '@';
buffer.append('@', status);
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;
}
@ -259,7 +262,7 @@ LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID)
return htp;
}
UBool
bool
LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& child)
{
return child.indexOf(root) == 0 &&
@ -271,5 +274,3 @@ U_NAMESPACE_END
/* !UCONFIG_NO_SERVICE */
#endif

View File

@ -28,7 +28,7 @@ public:
static Locale& initLocaleFromName(const UnicodeString& id, Locale& result);
static UnicodeString& initNameFromLocale(const Locale& locale, UnicodeString& result);
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

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.
errorCode=U_PATTERN_SYNTAX_ERROR;
return;
}
int32_t

View File

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

View File

@ -141,12 +141,12 @@ public:
/** Constructs only; init() should be called. */
ReorderingBuffer(const Normalizer2Impl &ni, UnicodeString &dest) :
impl(ni), str(dest),
start(NULL), reorderStart(NULL), limit(NULL),
start(nullptr), reorderStart(nullptr), limit(nullptr),
remainingCapacity(0), lastCC(0) {}
/** Constructs, removes the string contents, and initializes for a small initial capacity. */
ReorderingBuffer(const Normalizer2Impl &ni, UnicodeString &dest, UErrorCode &errorCode);
~ReorderingBuffer() {
if(start!=NULL) {
if (start != nullptr) {
str.releaseBuffer((int32_t)(limit-start));
}
}
@ -245,7 +245,7 @@ private:
*/
class U_COMMON_API Normalizer2Impl : public UObject {
public:
Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) { }
Normalizer2Impl() : normTrie(nullptr), fCanonIterData(nullptr) {}
virtual ~Normalizer2Impl();
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 *getCompositionsListForDecompYes(uint16_t norm16) const {
if(norm16<JAMO_L || MIN_NORMAL_MAYBE_YES<=norm16) {
return NULL;
return nullptr;
} else if(norm16<minMaybeYes) {
return getMapping(norm16); // for yesYes; if Jamo L: harmless empty list
} 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);
return;
}
U_CAPI const char * U_EXPORT2
@ -1622,7 +1621,7 @@ static const char *uprv_getPOSIXIDForCategory(int category)
* of nullptr, will modify the libc behavior.
*/
posixID = setlocale(category, nullptr);
if ((posixID == 0)
if ((posixID == nullptr)
|| (uprv_strcmp("C", 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");
if ((posixID == 0) || (posixID[0] == '\0')) {
#else
if (posixID == 0) {
if (posixID == nullptr) {
posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE");
if (posixID == 0) {
if (posixID == nullptr) {
#endif
posixID = getenv("LANG");
}
}
}
}
if ((posixID==0)
if ((posixID == nullptr)
|| (uprv_strcmp("C", 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* posixID = nullptr;
if (posixID == 0) {
if (posixID == nullptr) {
posixID = uprv_getPOSIXIDForCategory(LC_MESSAGES);
}
return posixID;

View File

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

View File

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

View File

@ -123,19 +123,66 @@ RBBINode::~RBBINode() {
break;
default:
delete fLeftChild;
// Avoid using a recursive implementation because of stack overflow problems.
// See bug ICU-22584.
// delete fLeftChild;
NRDeleteNode(fLeftChild);
fLeftChild = nullptr;
delete fRightChild;
// delete fRightChild;
NRDeleteNode(fRightChild);
fRightChild = nullptr;
}
delete fFirstPosSet;
delete fLastPosSet;
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.
//
//-------------------------------------------------------------------------
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) {
RBBINode *retNode = fLeftChild->cloneTree();
if (retNode != nullptr) {
@ -204,11 +261,11 @@ RBBINode *RBBINode::flattenVariables() {
}
if (fLeftChild != nullptr) {
fLeftChild = fLeftChild->flattenVariables();
fLeftChild = fLeftChild->flattenVariables(status, depth+1);
fLeftChild->fParent = this;
}
if (fRightChild != nullptr) {
fRightChild = fRightChild->flattenVariables();
fRightChild = fRightChild->flattenVariables(status, depth+1);
fRightChild->fParent = this;
}
return this;

View File

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

View File

@ -86,7 +86,8 @@ RBBIRuleBuilder::RBBIRuleBuilder(const UnicodeString &rules,
if (U_FAILURE(status)) {
return;
}
if(fSetBuilder == 0 || fScanner == 0 || fUSetNodes == 0 || fRuleStatusVals == 0) {
if (fSetBuilder == nullptr || fScanner == nullptr ||
fUSetNodes == nullptr || fRuleStatusVals == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
@ -156,7 +157,7 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() {
int32_t statusTableSize = align8(fRuleStatusVals->size() * sizeof(int32_t));
int32_t rulesLengthInUTF8 = 0;
u_strToUTF8WithSub(0, 0, &rulesLengthInUTF8,
u_strToUTF8WithSub(nullptr, 0, &rulesLengthInUTF8,
fStrippedRules.getBuffer(), fStrippedRules.length(),
0xfffd, nullptr, fStatus);
*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.
fixOpStack(RBBINode::precStart);
if (U_FAILURE(*fRB->fStatus)) {
break;
}
RBBINode *startExprNode = fNodeStack[fNodeStackPtr-2];
RBBINode *varRefNode = fNodeStack[fNodeStackPtr-1];
@ -312,6 +315,11 @@ UBool RBBIRuleScanner::doParseActions(int32_t action)
UErrorCode t = *fRB->fStatus;
*fRB->fStatus = U_ZERO_ERROR;
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.
@ -522,7 +530,13 @@ UBool RBBIRuleScanner::doParseActions(int32_t action)
n = fNodeStack[fNodeStackPtr];
uint32_t v = u_charDigitValue(fC.fChar);
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;
}
@ -762,6 +776,7 @@ void RBBIRuleScanner::findSetFor(const UnicodeString &s, RBBINode *node, Unicode
RBBINode *usetNode = new RBBINode(RBBINode::uset);
if (usetNode == nullptr) {
error(U_MEMORY_ALLOCATION_ERROR);
delete setToAdopt;
return;
}
usetNode->fInputSet = setToAdopt;
@ -796,8 +811,6 @@ void RBBIRuleScanner::findSetFor(const UnicodeString &s, RBBINode *node, Unicode
el->key = tkey;
el->val = usetNode;
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) {
c.fEscaped = true;
}
@ -1199,7 +1215,6 @@ RBBINode *RBBIRuleScanner::pushNewNode(RBBINode::NodeType t) {
//
//------------------------------------------------------------------------------
void RBBIRuleScanner::scanSet() {
UnicodeSet *uset;
ParsePosition pos;
int startPos;
int i;
@ -1211,12 +1226,12 @@ void RBBIRuleScanner::scanSet() {
pos.setIndex(fScanIndex);
startPos = fScanIndex;
UErrorCode localStatus = U_ZERO_ERROR;
uset = new UnicodeSet();
if (uset == nullptr) {
localStatus = U_MEMORY_ALLOCATION_ERROR;
} else {
uset->applyPatternIgnoreSpace(fRB->fRules, pos, fSymbolTable, localStatus);
LocalPointer<UnicodeSet> uset(new UnicodeSet(), localStatus);
if (U_FAILURE(localStatus)) {
error(localStatus);
return;
}
uset->applyPatternIgnoreSpace(fRB->fRules, pos, fSymbolTable, localStatus);
if (U_FAILURE(localStatus)) {
// TODO: Get more accurate position of the error from UnicodeSet's return info.
// 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());
#endif
error(localStatus);
delete uset;
return;
}
// Verify that the set contains at least one code point.
//
U_ASSERT(uset!=nullptr);
if (uset->isEmpty()) {
U_ASSERT(uset.isValid());
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.
// 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
// that occurs later on.
error(U_BRK_RULE_EMPTY_SET);
delete uset;
return;
}
@ -1246,7 +1263,7 @@ void RBBIRuleScanner::scanSet() {
// Don't just set fScanIndex because the line/char positions maintained
// for error reporting would be thrown off.
i = pos.getIndex();
for (;;) {
for (;U_SUCCESS(*fRB->fStatus);) {
if (fNextIndex >= i) {
break;
}
@ -1269,7 +1286,7 @@ void RBBIRuleScanner::scanSet() {
// character categories for run time engine.
// - Eliminates mulitiple instances of the same set.
// - 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
if (ch == 0xffff) {
retVal = fCachedSetLookup;
This->fCachedSetLookup = 0;
This->fCachedSetLookup = nullptr;
}
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
// parse tree for the substitution expression.
//
fTree = fTree->flattenVariables();
fTree = fTree->flattenVariables(*fStatus, 0);
if (U_FAILURE(*fStatus)) {
return;
}
#ifdef RBBI_DEBUG
if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ftree")) {
RBBIDebugPuts("\nParse tree after flattening variable references.");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -41,7 +41,6 @@
#include "uassert.h"
#include "ucase.h"
#include "ucasemap_imp.h"
#include "ustr_imp.h"
U_NAMESPACE_USE
@ -917,21 +916,20 @@ ucasemap_mapUTF8(int32_t caseLocale, uint32_t options, UCASEMAP_BREAK_ITERATOR_P
return 0;
}
CheckedArrayByteSink sink(dest, destCapacity);
if (edits != nullptr && (options & U_EDITS_NO_RESET) == 0) {
edits->reset();
}
int32_t reslen = ByteSinkUtil::viaByteSinkToTerminatedChars(
dest, destCapacity,
[&](ByteSink& sink, UErrorCode& status) {
stringCaseMapper(caseLocale, options, UCASEMAP_BREAK_ITERATOR
(const uint8_t *)src, srcLength, sink, edits, errorCode);
sink.Flush();
if (U_SUCCESS(errorCode)) {
if (sink.Overflowed()) {
errorCode = U_BUFFER_OVERFLOW_ERROR;
} else if (edits != nullptr) {
(const uint8_t *)src, srcLength, sink, edits, status);
},
errorCode);
if (U_SUCCESS(errorCode) && edits != nullptr) {
edits->copyErrorTo(errorCode);
}
}
return u_terminateChars(dest, destCapacity, sink.NumberOfBytesAppended(), &errorCode);
return reslen;
}
/* 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()
: CharacterIterator(),
text(0)
text(nullptr)
{
// never default construct!
}
UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
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)
{
}
@ -35,7 +35,7 @@ UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
int32_t length,
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)
{
}
@ -45,7 +45,8 @@ UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
int32_t textBegin,
int32_t textEnd,
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)
{
}
@ -352,7 +353,7 @@ UCharCharacterIterator::move32(int32_t delta, CharacterIterator::EOrigin origin)
void UCharCharacterIterator::setText(ConstChar16Ptr newText,
int32_t newTextLength) {
text = newText;
if(newText == 0 || newTextLength < 0) {
if (newText == nullptr || newTextLength < 0) {
newTextLength = 0;
}
end = textLength = newTextLength;

View File

@ -473,8 +473,6 @@ ucnv_setSubstChars (UConverter * converter,
* we set subChar1 to 0.
*/
converter->subChar1 = 0;
return;
}
U_CAPI void U_EXPORT2
@ -1754,7 +1752,7 @@ ucnv_fromUChars(UConverter *cnv,
destLimit=dest+destCapacity;
/* 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);
/* if an overflow occurs, then get the preflighting length */
@ -1765,7 +1763,7 @@ ucnv_fromUChars(UConverter *cnv,
do {
dest=buffer;
*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);
} while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
}
@ -1810,7 +1808,7 @@ ucnv_toUChars(UConverter *cnv,
destLimit=dest+destCapacity;
/* 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);
/* if an overflow occurs, then get the preflighting length */
@ -1822,7 +1820,7 @@ ucnv_toUChars(UConverter *cnv,
do {
dest=buffer;
*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);
}
while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);

View File

@ -109,7 +109,6 @@ UCNV_FROM_U_CALLBACK_STOP (
*err = U_ZERO_ERROR;
}
/* 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 */
(void)context; (void)toUArgs; (void)codePoints; (void)length; (void)reason; (void)err;
return;
}
U_CAPI void U_EXPORT2
@ -353,8 +351,6 @@ UCNV_FROM_U_CALLBACK_ESCAPE (
*err = err2;
return;
}
return;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -22,7 +22,6 @@
#include "unicode/usetiter.h"
#include "unicode/utf16.h"
#include "ustr_imp.h"
#include "bytesinkutil.h"
#include "charstr.h"
#include "cmemory.h"
#include "cstring.h"
@ -296,7 +295,7 @@ myUCharsToChars(char* resultOfLen4, const char16_t* currency) {
static const int32_t*
_findMetaData(const char16_t* currency, UErrorCode& ec) {
if (currency == 0 || *currency == 0) {
if (currency == nullptr || *currency == 0) {
if (U_SUCCESS(ec)) {
ec = U_ILLEGAL_ARGUMENT_ERROR;
}
@ -349,10 +348,10 @@ _findMetaData(const char16_t* currency, UErrorCode& ec) {
// -------------------------------------
static void
idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCode* ec)
static CharString
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;
static UMutex gCRegLock;
static CReg* gCRegHead = 0;
static CReg* gCRegHead = nullptr;
struct CReg : public icu::UMemory {
CReg *next;
@ -379,7 +378,7 @@ struct CReg : public icu::UMemory {
char id[ULOC_FULLNAME_CAPACITY];
CReg(const char16_t* _iso, const char* _id)
: next(0)
: next(nullptr)
{
int32_t len = (int32_t)uprv_strlen(_id);
if (len > (int32_t)(sizeof(id)-1)) {
@ -408,7 +407,7 @@ struct CReg : public icu::UMemory {
}
*status = U_MEMORY_ALLOCATION_ERROR;
}
return 0;
return nullptr;
}
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)
{
if (status && U_SUCCESS(*status)) {
char id[ULOC_FULLNAME_CAPACITY];
idForLocale(locale, id, sizeof(id), status);
return CReg::reg(isoCode, id, status);
CharString id = idForLocale(locale, status);
return CReg::reg(isoCode, id.data(), status);
}
return nullptr;
}
@ -524,11 +522,7 @@ ucurr_forLocale(const char* locale,
}
UErrorCode localStatus = U_ZERO_ERROR;
CharString currency;
{
CharStringByteSink sink(&currency);
ulocimp_getKeywordValue(locale, "currency", sink, &localStatus);
}
CharString currency = ulocimp_getKeywordValue(locale, "currency", localStatus);
int32_t resLen = currency.length();
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'
char id[ULOC_FULLNAME_CAPACITY];
idForLocale(locale, id, UPRV_LENGTHOF(id), ec);
CharString id = idForLocale(locale, ec);
if (U_FAILURE(*ec)) {
return 0;
}
#if !UCONFIG_NO_SERVICE
const char16_t* result = CReg::get(id);
const char16_t* result = CReg::get(id.data());
if (result) {
if(buffCapacity > u_strlen(result)) {
u_strcpy(buff, result);
@ -557,13 +550,13 @@ ucurr_forLocale(const char* locale,
}
#endif
// 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) {
idDelim[0] = 0;
id.truncate(idDelim - id.data());
}
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.
// This is what we would get.
localStatus = U_MISSING_RESOURCE_ERROR;
@ -572,7 +565,7 @@ ucurr_forLocale(const char* locale,
localStatus = U_ZERO_ERROR;
UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &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
// Prefer to use currencies that are legal tender.
if (U_SUCCESS(localStatus)) {
@ -602,13 +595,9 @@ ucurr_forLocale(const char* locale,
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.
CharString parent;
{
CharStringByteSink sink(&parent);
ulocimp_getParent(locale, sink, ec);
}
CharString parent = ulocimp_getParent(locale, *ec);
*ec = U_USING_FALLBACK_WARNING;
// TODO: Loop over the parent rather than recursing and
// looking again for a currency keyword.
@ -647,10 +636,7 @@ static UBool fallback(CharString& loc) {
loc.truncate(3);
loc.append("001", status);
} else {
CharString tmp;
CharStringByteSink sink(&tmp);
ulocimp_getParent(loc.data(), sink, &status);
loc = std::move(tmp);
loc = ulocimp_getParent(loc.data(), status);
}
/*
char *i = uprv_strrchr(loc, '_');
@ -683,13 +669,13 @@ ucurr_getName(const char16_t* currency,
//|}
if (U_FAILURE(*ec)) {
return 0;
return nullptr;
}
int32_t choice = (int32_t) nameStyle;
if (choice < 0 || choice > 4) {
*ec = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
return nullptr;
}
// In the future, resource bundles may implement multi-level
@ -705,14 +691,10 @@ ucurr_getName(const char16_t* currency,
// this function.
UErrorCode ec2 = U_ZERO_ERROR;
CharString loc;
{
CharStringByteSink sink(&loc);
ulocimp_getName(locale, sink, &ec2);
}
CharString loc = ulocimp_getName(locale, ec2);
if (U_FAILURE(ec2)) {
*ec = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
return nullptr;
}
char buf[ISO_CURRENCY_CODE_LENGTH+1];
@ -739,7 +721,7 @@ ucurr_getName(const char16_t* currency,
break;
default:
*ec = U_UNSUPPORTED_ERROR;
return 0;
return nullptr;
}
key.append("/", ec2);
key.append(buf, ec2);
@ -800,21 +782,17 @@ ucurr_getPluralName(const char16_t* currency,
//|}
if (U_FAILURE(*ec)) {
return 0;
return nullptr;
}
// Use a separate UErrorCode here that does not propagate out of
// this function.
UErrorCode ec2 = U_ZERO_ERROR;
CharString loc;
{
CharStringByteSink sink(&loc);
ulocimp_getName(locale, sink, &ec2);
}
CharString loc = ulocimp_getName(locale, ec2);
if (U_FAILURE(ec2)) {
*ec = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
return nullptr;
}
char buf[ISO_CURRENCY_CODE_LENGTH+1];
@ -1002,11 +980,7 @@ collectCurrencyNames(const char* locale,
// Look up the Currencies resource for the given locale.
UErrorCode ec2 = U_ZERO_ERROR;
CharString loc;
{
CharStringByteSink sink(&loc);
ulocimp_getName(locale, sink, &ec2);
}
CharString loc = ulocimp_getName(locale, ec2);
if (U_FAILURE(ec2)) {
ec = U_ILLEGAL_ARGUMENT_ERROR;
}
@ -1390,7 +1364,6 @@ searchCurrencyName(const CurrencyNameStruct* currencyNames,
break;
}
}
return;
}
//========================= currency name cache =====================
@ -1447,7 +1420,7 @@ currency_cache_cleanup() {
for (int32_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
if (currCache[i]) {
deleteCacheEntry(currCache[i]);
currCache[i] = 0;
currCache[i] = nullptr;
}
}
return true;
@ -2030,6 +2003,7 @@ static const struct CurrencyList {
{"XBC", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
{"XBD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
{"XCD", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"XCG", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"XDR", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
{"XEU", UCURR_UNCOMMON|UCURR_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) {
if (U_FAILURE(status)) { return; }
for (auto& entry : unisets::kCurrencyEntries) {
for (const auto& entry : unisets::kCurrencyEntries) {
UnicodeString exemplar(entry.exemplar);
const UnicodeSet* set = unisets::get(entry.key);
if (set == nullptr) { return; }
@ -2325,10 +2299,9 @@ ucurr_countCurrencies(const char* locale,
{
// local variables
UErrorCode localStatus = U_ZERO_ERROR;
char id[ULOC_FULLNAME_CAPACITY];
// get country or country_variant in `id'
idForLocale(locale, id, sizeof(id), ec);
CharString id = idForLocale(locale, ec);
if (U_FAILURE(*ec))
{
@ -2336,10 +2309,10 @@ ucurr_countCurrencies(const char* locale,
}
// Remove variants, which is only needed for registration.
char *idDelim = strchr(id, VAR_DELIM);
char *idDelim = strchr(id.data(), VAR_DELIM);
if (idDelim)
{
idDelim[0] = 0;
id.truncate(idDelim - id.data());
}
// 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);
// 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
if (U_SUCCESS(localStatus))
@ -2440,20 +2413,19 @@ ucurr_forLocaleAndDate(const char* locale,
{
// local variables
UErrorCode localStatus = U_ZERO_ERROR;
char id[ULOC_FULLNAME_CAPACITY];
// get country or country_variant in `id'
idForLocale(locale, id, sizeof(id), ec);
CharString id = idForLocale(locale, ec);
if (U_FAILURE(*ec))
{
return 0;
}
// Remove variants, which is only needed for registration.
char *idDelim = strchr(id, VAR_DELIM);
char *idDelim = strchr(id.data(), VAR_DELIM);
if (idDelim)
{
idDelim[0] = 0;
id.truncate(idDelim - id.data());
}
// 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);
// 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
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) {
// Resolve region
char prefRegion[ULOC_COUNTRY_CAPACITY];
ulocimp_getRegionForSupplementalData(locale, true, prefRegion, sizeof(prefRegion), status);
CharString prefRegion = ulocimp_getRegionForSupplementalData(locale, true, *status);
// Read value from supplementalData
UList *values = ulist_createEmptyList(status);
@ -2621,7 +2592,7 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key,
break;
}
const char *region = ures_getKey(&bundlekey);
UBool isPrefRegion = uprv_strcmp(region, prefRegion) == 0 ? true : false;
UBool isPrefRegion = prefRegion == region;
if (!isPrefRegion && commonlyUsed) {
// With commonlyUsed=true, we do not put
// 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) {
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);
if (U_SUCCESS(status)) {
char alphaCode[ISO_CURRENCY_CODE_LENGTH+1];

View File

@ -850,8 +850,8 @@ static UBool extendICUData(UErrorCode *pErr)
UDataMemory_init(&copyPData);
if(pData != nullptr) {
UDatamemory_assign(&copyPData, pData);
copyPData.map = 0; /* The mapping for this data is owned by the hash table */
copyPData.mapAddr = 0; /* which will unmap it when ICU is shut down. */
copyPData.map = nullptr; /* The mapping for this data is owned by the hash table */
copyPData.mapAddr = nullptr; /* which will unmap it when ICU is shut down. */
/* CommonICUData is also unmapped when ICU is shut down.*/
/* To avoid unmapping the data twice, zero out the map */
/* 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
) {
*pErrorCode=U_UNSUPPORTED_ERROR;
return 0;
return nullptr;
}
inIsBigEndian=(UBool)pHeader->info.isBigEndian;
@ -461,7 +461,7 @@ udata_openSwapperForInputData(const void *data, int32_t length,
(length>=0 && length<headerSize)
) {
*pErrorCode=U_UNSUPPORTED_ERROR;
return 0;
return nullptr;
}
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={
0, 0, 0, 0, 0, 0,
nullptr, 0, 0, 0, 0, 0,
noopGetIndex,
noopMove,
noopHasNext,
@ -197,7 +197,7 @@ stringIteratorSetState(UCharIterator *iter, uint32_t state, UErrorCode *pErrorCo
}
static const UCharIterator stringIterator={
0, 0, 0, 0, 0, 0,
nullptr, 0, 0, 0, 0, 0,
stringIteratorGetIndex,
stringIteratorMove,
stringIteratorHasNext,
@ -212,8 +212,8 @@ static const UCharIterator stringIterator={
U_CAPI void U_EXPORT2
uiter_setString(UCharIterator *iter, const char16_t *s, int32_t length) {
if(iter!=0) {
if(s!=0 && length>=-1) {
if (iter != nullptr) {
if (s != nullptr && length >= -1) {
*iter=stringIterator;
iter->context=s;
if(length>=0) {
@ -283,7 +283,7 @@ utf16BEIteratorPrevious(UCharIterator *iter) {
}
static const UCharIterator utf16BEIterator={
0, 0, 0, 0, 0, 0,
nullptr, 0, 0, 0, 0, 0,
stringIteratorGetIndex,
stringIteratorMove,
stringIteratorHasNext,
@ -457,7 +457,7 @@ characterIteratorSetState(UCharIterator *iter, uint32_t state, UErrorCode *pErro
}
static const UCharIterator characterIteratorWrapper={
0, 0, 0, 0, 0, 0,
nullptr, 0, 0, 0, 0, 0,
characterIteratorGetIndex,
characterIteratorMove,
characterIteratorHasNext,
@ -472,8 +472,8 @@ static const UCharIterator characterIteratorWrapper={
U_CAPI void U_EXPORT2
uiter_setCharacterIterator(UCharIterator *iter, CharacterIterator *charIter) {
if(iter!=0) {
if(charIter!=0) {
if (iter != nullptr) {
if (charIter != nullptr) {
*iter=characterIteratorWrapper;
iter->context=charIter;
} else {
@ -521,7 +521,7 @@ replaceableIteratorPrevious(UCharIterator *iter) {
}
static const UCharIterator replaceableIterator={
0, 0, 0, 0, 0, 0,
nullptr, 0, 0, 0, 0, 0,
stringIteratorGetIndex,
stringIteratorMove,
stringIteratorHasNext,
@ -536,8 +536,8 @@ static const UCharIterator replaceableIterator={
U_CAPI void U_EXPORT2
uiter_setReplaceable(UCharIterator *iter, const Replaceable *rep) {
if(iter!=0) {
if(rep!=0) {
if (iter != nullptr) {
if (rep != nullptr) {
*iter=replaceableIterator;
iter->context=rep;
iter->limit=iter->length=rep->length();
@ -987,7 +987,7 @@ utf8IteratorSetState(UCharIterator *iter,
}
static const UCharIterator utf8Iterator={
0, 0, 0, 0, 0, 0,
nullptr, 0, 0, 0, 0, 0,
utf8IteratorGetIndex,
utf8IteratorMove,
utf8IteratorHasNext,
@ -1002,8 +1002,8 @@ static const UCharIterator utf8Iterator={
U_CAPI void U_EXPORT2
uiter_setUTF8(UCharIterator *iter, const char *s, int32_t length) {
if(iter!=0) {
if(s!=0 && length>=-1) {
if (iter != nullptr) {
if (s != nullptr && length >= -1) {
*iter=utf8Iterator;
iter->context=s;
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
namespace {
static void U_CALLCONV
void U_CALLCONV
initFromResourceBundle(UErrorCode& sts) {
U_NAMESPACE_USE
ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KEY_TYPE, uloc_key_type_cleanup);
@ -141,7 +142,7 @@ initFromResourceBundle(UErrorCode& sts) {
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);
if (U_FAILURE(sts)) {
@ -351,7 +352,7 @@ initFromResourceBundle(UErrorCode& sts) {
}
}
static UBool
bool
init() {
UErrorCode sts = U_ZERO_ERROR;
umtx_initOnce(gLocExtKeyMapInitOnce, &initFromResourceBundle, sts);
@ -361,7 +362,7 @@ init() {
return true;
}
static UBool
bool
isSpecialTypeCodepoints(const char* val) {
int32_t subtagLen = 0;
const char* p = val;
@ -383,7 +384,7 @@ isSpecialTypeCodepoints(const char* val) {
return (subtagLen >= 4 && subtagLen <= 6);
}
static UBool
bool
isSpecialTypeReorderCode(const char* val) {
int32_t subtagLen = 0;
const char* p = val;
@ -403,7 +404,7 @@ isSpecialTypeReorderCode(const char* val) {
return (subtagLen >=3 && subtagLen <=8);
}
static UBool
bool
isSpecialTypeRgKeyValue(const char* val) {
int32_t subtagLen = 0;
const char* p = val;
@ -419,7 +420,9 @@ isSpecialTypeRgKeyValue(const char* val) {
return (subtagLen == 6);
}
U_CFUNC const char*
} // namespace
U_EXPORT const char*
ulocimp_toBcpKey(const char* key) {
if (!init()) {
return nullptr;
@ -432,7 +435,7 @@ ulocimp_toBcpKey(const char* key) {
return nullptr;
}
U_CFUNC const char*
U_EXPORT const char*
ulocimp_toLegacyKey(const char* key) {
if (!init()) {
return nullptr;
@ -445,8 +448,8 @@ ulocimp_toLegacyKey(const char* key) {
return nullptr;
}
U_CFUNC const char*
ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType) {
U_EXPORT const char*
ulocimp_toBcpType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType) {
if (isKnownKey != nullptr) {
*isKnownKey = false;
}
@ -468,7 +471,7 @@ ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* i
return t->bcpId;
}
if (keyData->specialTypes != SPECIALTYPE_NONE) {
UBool matched = false;
bool matched = false;
if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) {
matched = isSpecialTypeCodepoints(type);
}
@ -490,8 +493,8 @@ ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* i
}
U_CFUNC const char*
ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType) {
U_EXPORT const char*
ulocimp_toLegacyType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType) {
if (isKnownKey != nullptr) {
*isKnownKey = false;
}
@ -513,7 +516,7 @@ ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool
return t->legacyId;
}
if (keyData->specialTypes != SPECIALTYPE_NONE) {
UBool matched = false;
bool matched = false;
if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) {
matched = isSpecialTypeCodepoints(type);
}
@ -533,4 +536,3 @@ ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool
}
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.
// License & terms of use: http://www.unicode.org/copyright.html
//
#include "unicode/bytestream.h"
#include "unicode/errorcode.h"
#include "unicode/stringpiece.h"
#include "unicode/utypes.h"
@ -8,9 +9,9 @@
#include "unicode/ulocale.h"
#include "unicode/locid.h"
#include "bytesinkutil.h"
#include "charstr.h"
#include "cmemory.h"
#include "ustr_imp.h"
U_NAMESPACE_USE
#define EXTERNAL(i) (reinterpret_cast<ULocale*>(i))
@ -19,15 +20,17 @@ U_NAMESPACE_USE
ULocale*
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);
if (U_FAILURE(*err)) return nullptr;
if (U_FAILURE(*err)) { return nullptr; }
return EXTERNAL(icu::Locale::createFromName(str.data()).clone());
}
ULocale*
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);
if (U_FAILURE(*err)) return nullptr;
if (U_FAILURE(*err)) { return nullptr; }
return EXTERNAL(l.clone());
}
@ -53,20 +56,14 @@ int32_t ulocale_get ##N ( \
*err = U_ILLEGAL_ARGUMENT_ERROR; \
return 0; \
} \
CheckedArrayByteSink sink(valueBuffer, bufferCapacity); \
return ByteSinkUtil::viaByteSinkToTerminatedChars( \
valueBuffer, bufferCapacity, \
[&](ByteSink& sink, UErrorCode& status) { \
CONST_INTERNAL(locale)->get ## N( \
keywordLength < 0 ? StringPiece(keyword) : StringPiece(keyword, keywordLength), \
sink, *err); \
int32_t reslen = sink.NumberOfBytesAppended(); \
if (U_FAILURE(*err)) { \
return reslen; \
} \
if (sink.Overflowed()) { \
*err = U_BUFFER_OVERFLOW_ERROR; \
} else { \
u_terminateChars(valueBuffer, bufferCapacity, reslen, err); \
} \
return reslen; \
sink, status); \
}, \
*err); \
}
#define IMPL_ULOCALE_GET_KEYWORDS(N) \

View File

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

View File

@ -10,6 +10,8 @@
#ifndef ULOCIMP_H
#define ULOCIMP_H
#include <cstddef>
#include "unicode/bytestream.h"
#include "unicode/uloc.h"
@ -40,8 +42,10 @@ uloc_getTableStringWithFallback(
int32_t *pLength,
UErrorCode *pErrorCode);
namespace {
/*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*
uloc_getCurrentCountryID(const char* oldID);
@ -49,53 +53,134 @@ uloc_getCurrentCountryID(const char* oldID);
U_CFUNC const char*
uloc_getCurrentLanguageID(const char* oldID);
U_CFUNC void
ulocimp_getKeywords(const char *localeID,
U_EXPORT icu::CharString
ulocimp_getKeywords(const char* localeID,
char prev,
bool valuesToo,
UErrorCode& status);
U_EXPORT void
ulocimp_getKeywords(const char* localeID,
char prev,
icu::ByteSink& sink,
UBool valuesToo,
UErrorCode *status);
bool valuesToo,
UErrorCode& status);
icu::CharString U_EXPORT2
ulocimp_getLanguage(const char *localeID,
const char **pEnd,
UErrorCode &status);
U_EXPORT icu::CharString
ulocimp_getName(const char* localeID,
UErrorCode& err);
icu::CharString U_EXPORT2
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
U_EXPORT void
ulocimp_getName(const char* localeID,
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,
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,
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,
const char* keywordName,
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,
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.
@ -116,11 +201,17 @@ ulocimp_getParent(const char* localeID,
*
* @internal ICU 64
*/
U_CAPI void U_EXPORT2
U_EXPORT void
ulocimp_toLanguageTag(const char* localeID,
icu::ByteSink& sink,
UBool strict,
UErrorCode* err);
bool strict,
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.
@ -148,12 +239,12 @@ ulocimp_toLanguageTag(const char* localeID,
* failed.
* @internal ICU 63
*/
U_CAPI void U_EXPORT2
U_EXPORT void
ulocimp_forLanguageTag(const char* langtag,
int32_t tagLen,
icu::ByteSink& sink,
int32_t* parsedLength,
UErrorCode* err);
UErrorCode& err);
/**
* 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
* (3) if inferRegion is true, the region suggested by
* getLikelySubtags on the localeID.
* If no region is found, returns length 0.
* If no region is found, returns an empty string.
*
* @param localeID
* The complete locale ID (with keywords) from which
@ -169,20 +260,19 @@ ulocimp_forLanguageTag(const char* langtag,
* @param inferRegion
* If true, will try to infer region from localeID if
* 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
* Pointer to in/out UErrorCode value for latest status.
* @return
* The length of any region code found, or 0 if none.
* The region code found, empty if none found.
* @internal ICU 57
*/
U_CAPI int32_t U_EXPORT2
ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
char *region, int32_t regionCapacity, UErrorCode* status);
U_EXPORT icu::CharString
ulocimp_getRegionForSupplementalData(const char *localeID, bool inferRegion,
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
@ -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.
* @internal ICU 64
*/
U_CAPI void U_EXPORT2
U_EXPORT void
ulocimp_addLikelySubtags(const char* localeID,
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
@ -248,70 +343,72 @@ ulocimp_addLikelySubtags(const char* localeID,
* or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR.
* @internal ICU 64
*/
U_CAPI void U_EXPORT2
U_EXPORT void
ulocimp_minimizeSubtags(const char* localeID,
icu::ByteSink& sink,
bool favorScript,
UErrorCode* err);
UErrorCode& err);
U_CAPI const char * U_EXPORT2
locale_getKeywordsStart(const char *localeID);
U_CFUNC UBool
bool
ultag_isExtensionSubtags(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isLanguageSubtag(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isPrivateuseValueSubtags(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isRegionSubtag(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isScriptSubtag(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isTransformedExtensionSubtags(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isUnicodeExtensionSubtags(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isUnicodeLocaleAttribute(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isUnicodeLocaleAttributes(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isUnicodeLocaleKey(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isUnicodeLocaleType(const char* s, int32_t len);
U_CFUNC UBool
bool
ultag_isVariantSubtags(const char* s, int32_t len);
U_CAPI const char * U_EXPORT2
ultag_getTKeyStart(const char *localeID);
const char*
ultag_getTKeyStart(const char* localeID);
U_CFUNC const char*
U_EXPORT const char*
ulocimp_toBcpKey(const char* key);
U_CFUNC const char*
U_EXPORT const char*
ulocimp_toLegacyKey(const char* key);
U_CFUNC const char*
ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType);
U_EXPORT const char*
ulocimp_toBcpType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType);
U_CFUNC const char*
ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType);
U_EXPORT const char*
ulocimp_toLegacyType(const char* key, const char* type, bool* isKnownKey, bool* isSpecialType);
/* 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.
U_CAPI bool ulocimp_isCanonicalizedLocaleForTest(const char* localeName);
U_EXPORT bool
ulocimp_isCanonicalizedLocaleForTest(const char* localeName);
#endif

View File

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

View File

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

View File

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

View File

@ -128,9 +128,10 @@ public:
* @param skipZeros determine if skip zeros
* @param result the results in a set.
* @param status Fill-in parameter which receives the status of this operation.
* @param depth depth of the call.
* @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 */
/**
@ -182,8 +183,8 @@ private:
// transient fields
UnicodeString buffer;
const Normalizer2 &nfd;
const Normalizer2Impl &nfcImpl;
const Normalizer2 *nfd;
const Normalizer2Impl *nfcImpl;
// 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)

View File

@ -133,7 +133,7 @@ public:
* @return the hash code.
* @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
@ -142,7 +142,7 @@ public:
* @return a UClassID for this ForwardCharacterIterator
* @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
@ -152,7 +152,7 @@ public:
* @return the current code unit.
* @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
@ -162,7 +162,7 @@ public:
* @return the current code point.
* @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
@ -389,7 +389,7 @@ public:
* @return the first code unit in its iteration range.
* @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
@ -399,7 +399,7 @@ public:
* @return the first code unit in its iteration range.
* @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
@ -410,7 +410,7 @@ public:
* @return the first code point in its iteration range.
* @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
@ -420,7 +420,7 @@ public:
* @return the first code point in its iteration range.
* @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
@ -438,7 +438,7 @@ public:
* @return the last code unit.
* @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
@ -447,7 +447,7 @@ public:
* @return the last code point.
* @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
@ -486,14 +486,14 @@ public:
* @return the current code unit.
* @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.
* @return the current code point.
* @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
@ -502,7 +502,7 @@ public:
* @return the next code unit.
* @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
@ -514,7 +514,7 @@ public:
* @return the next code point.
* @stable ICU 2.0
*/
virtual UChar32 next32(void) = 0;
virtual UChar32 next32() = 0;
/**
* Advances to the previous code unit in the iteration range
@ -523,7 +523,7 @@ public:
* @return the previous code unit.
* @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
@ -532,7 +532,7 @@ public:
* @return the previous code point.
* @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
@ -555,7 +555,7 @@ public:
* object of the character returned by first().
* @stable ICU 2.0
*/
inline int32_t startIndex(void) const;
inline int32_t startIndex() const;
/**
* Returns the numeric index in the underlying text-storage
@ -566,7 +566,7 @@ public:
* returned by last().
* @stable ICU 2.0
*/
inline int32_t endIndex(void) const;
inline int32_t endIndex() const;
/**
* Returns the numeric index in the underlying text-storage
@ -576,7 +576,7 @@ public:
* the character the iterator currently refers to
* @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
@ -708,22 +708,22 @@ CharacterIterator::setToEnd() {
}
inline int32_t
CharacterIterator::startIndex(void) const {
CharacterIterator::startIndex() const {
return begin;
}
inline int32_t
CharacterIterator::endIndex(void) const {
CharacterIterator::endIndex() const {
return end;
}
inline int32_t
CharacterIterator::getIndex(void) const {
CharacterIterator::getIndex() const {
return pos;
}
inline int32_t
CharacterIterator::getLength(void) const {
CharacterIterator::getLength() const {
return textLength;
}

View File

@ -143,6 +143,11 @@
* <td>icu::MessageFormat</td>
* </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>ulistformatter.h</td>
* <td>icu::ListFormatter</td>

View File

@ -76,7 +76,7 @@ public:
* @return The class ID for all objects of this class.
* @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
@ -89,8 +89,7 @@ public:
* other classes have different class IDs.
* @stable ICU 4.0
*/
virtual UClassID getDynamicClassID(void) const override;
virtual UClassID getDynamicClassID() const override;
/**
* Copy constructor.

View File

@ -11,6 +11,8 @@
#if U_SHOW_CPLUSPLUS_API
#include <optional>
#include "unicode/locid.h"
#include "unicode/stringpiece.h"
#include "unicode/uobject.h"
@ -133,10 +135,10 @@ U_NAMESPACE_BEGIN
struct LSR;
class LikelySubtags;
class LocaleDistance;
class LocaleLsrIterator;
class UVector;
class XLikelySubtags;
/**
* 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 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;
int32_t thresholdDistance;
int32_t demotionPerDesiredLocale;

View File

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

View File

@ -195,51 +195,50 @@ class UnicodeString;
class U_COMMON_API Locale : public UObject {
public:
/** 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 */
static const Locale &U_EXPORT2 getEnglish(void);
static const Locale& U_EXPORT2 getEnglish();
/** 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 */
static const Locale &U_EXPORT2 getGerman(void);
static const Locale& U_EXPORT2 getGerman();
/** 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 */
static const Locale &U_EXPORT2 getJapanese(void);
static const Locale& U_EXPORT2 getJapanese();
/** 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 */
static const Locale &U_EXPORT2 getChinese(void);
static const Locale& U_EXPORT2 getChinese();
/** 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 */
static const Locale &U_EXPORT2 getTraditionalChinese(void);
static const Locale& U_EXPORT2 getTraditionalChinese();
/** 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 */
static const Locale &U_EXPORT2 getGermany(void);
static const Locale& U_EXPORT2 getGermany();
/** 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 */
static const Locale &U_EXPORT2 getJapan(void);
static const Locale& U_EXPORT2 getJapan();
/** 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 */
static const Locale &U_EXPORT2 getChina(void);
static const Locale& U_EXPORT2 getChina();
/** 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 */
static const Locale &U_EXPORT2 getTaiwan(void);
static const Locale& U_EXPORT2 getTaiwan();
/** 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 */
static const Locale &U_EXPORT2 getUS(void);
static const Locale& U_EXPORT2 getUS();
/** 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 */
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.
@ -274,10 +273,10 @@ public:
* @see uloc_getDefault
* @stable ICU 2.0
*/
Locale( const char * language,
const char * country = 0,
const char * variant = 0,
const char * keywordsAndValues = 0);
Locale(const char* language,
const char* country = nullptr,
const char* variant = nullptr,
const char* keywordsAndValues = nullptr);
/**
* Initializes a Locale object from another Locale object.
@ -370,7 +369,7 @@ public:
* @system
* @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,
@ -518,20 +517,20 @@ public:
* 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.
*
* For example, "und-Zzzz" cannot be maximized, since there is no
* For example, "sh" cannot be maximized, since there is no
* reasonable maximization.
*
* Examples:
*
* "und_Zzzz" 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"
*
* "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.)
*
* "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.)
* "zh_Hani" maximizes to "zh_Hani_CN"
*
* @param status error information if maximizing this Locale failed.
* 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.
* @stable ICU 2.0
*/
uint32_t getLCID(void) const;
uint32_t getLCID() const;
/**
* Returns whether this locale's script is written right-to-left.
@ -944,7 +943,7 @@ public:
* Generates a hash code for the locale.
* @stable ICU 2.0
*/
int32_t hashCode(void) const;
int32_t hashCode() const;
/**
* 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
* @stable ICU 2.1
*/
inline UBool isBogus(void) const;
inline UBool isBogus() const;
/**
* Returns a list of all installed locales.
@ -1147,7 +1146,7 @@ private:
/**
* Initialize the locale cache for commonly used locales
*/
static Locale *getLocaleCache(void);
static Locale* getLocaleCache();
char language[ULOC_LANG_CAPACITY];
char script[ULOC_SCRIPT_CAPACITY];
@ -1184,6 +1183,7 @@ Locale::operator!=(const Locale& other) const
template<typename StringClass> inline StringClass
Locale::toLanguageTag(UErrorCode& status) const
{
if (U_FAILURE(status)) { return {}; }
StringClass result;
StringByteSink<StringClass> sink(&result);
toLanguageTag(sink, status);
@ -1211,7 +1211,7 @@ Locale::getScript() const
inline const char *
Locale::getVariant() const
{
return &baseName[variantBegin];
return fIsBogus ? "" : &baseName[variantBegin];
}
inline const char *
@ -1223,6 +1223,7 @@ Locale::getName() const
template<typename StringClass, typename OutputIterator> inline void
Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
{
if (U_FAILURE(status)) { return; }
LocalPointer<StringEnumeration> keys(createKeywords(status));
if (U_FAILURE(status) || keys.isNull()) {
return;
@ -1240,6 +1241,7 @@ Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
template<typename StringClass, typename OutputIterator> inline void
Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
{
if (U_FAILURE(status)) { return; }
LocalPointer<StringEnumeration> keys(createUnicodeKeywords(status));
if (U_FAILURE(status) || keys.isNull()) {
return;
@ -1257,6 +1259,7 @@ Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
template<typename StringClass> inline StringClass
Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const
{
if (U_FAILURE(status)) { return {}; }
StringClass result;
StringByteSink<StringClass> sink(&result);
getKeywordValue(keywordName, sink, status);
@ -1266,6 +1269,7 @@ Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const
template<typename StringClass> inline StringClass
Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const
{
if (U_FAILURE(status)) { return {}; }
StringClass result;
StringByteSink<StringClass> sink(&result);
getUnicodeKeywordValue(keywordName, sink, status);
@ -1273,7 +1277,7 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) cons
}
inline UBool
Locale::isBogus(void) const {
Locale::isBogus() const {
return fIsBogus;
}

View File

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

View File

@ -129,7 +129,7 @@ public:
* @return the current index.
* @stable ICU 2.0
*/
inline int32_t getIndex(void) const;
inline int32_t getIndex() const;
/**
* Set the current parse position.
@ -152,7 +152,7 @@ public:
* error index has not been set.
* @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.

View File

@ -206,6 +206,17 @@
# define U_PLATFORM U_PF_UNKNOWN
#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
* Defined if this is Windows with Cygwin, but using MSVC rather than gcc.
@ -302,51 +313,6 @@
# define U_PLATFORM_IS_DARWIN_BASED 0
#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 */
/*===========================================================================*/
@ -507,6 +473,8 @@
/* Otherwise use the predefined value. */
#elif !defined(__cplusplus)
# 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)
# define U_CPLUSPLUS_VERSION 14
#elif __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
@ -754,9 +722,9 @@
/*
* Notes:
* 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
# else
# define U_HAVE_CHAR16_T 0

View File

@ -42,89 +42,25 @@
/* NULL, size_t, wchar_t */
#include <stddef.h>
/*
* 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. */
/* More platform-specific definitions. */
#include "unicode/platform.h"
/*===========================================================================*/
/* 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>
#if U_PLATFORM == U_PF_OS390
/* The features header is needed to get (u)int64_t sometimes. */
#include <features.h>
/* z/OS has <stdint.h>, but some versions are missing uint8_t (APAR PK62248). */
#if !defined(__uint8_t)
#define __uint8_t 1
typedef unsigned char uint8_t;
// C++11 and C11 both specify that the data type char16_t should exist, C++11
// as a keyword and C11 as a typedef in the uchar.h header file, but not all
// implementations (looking at you, Apple, spring 2024) actually do this, so
// ICU4C must detect and deal with that.
#if !defined(__cplusplus) && !defined(U_IN_DOXYGEN)
# if U_HAVE_CHAR16_T
# include <uchar.h>
# else
typedef uint16_t char16_t;
# 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 */

View File

@ -44,7 +44,7 @@ class UnhandledEngine;
class UStack;
#ifndef U_HIDE_DRAFT_API
#ifndef U_HIDE_INTERNAL_API
/**
* 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
@ -103,7 +103,7 @@ class ExternalBreakEngine : public UObject {
int32_t* foundBreaks, int32_t foundBreaksCapacity,
UErrorCode& status) const = 0;
};
#endif /* U_HIDE_DRAFT_API */
#endif /* U_HIDE_INTERNAL_API */
/**
@ -388,14 +388,14 @@ public:
* @return A hash code
* @stable ICU 2.0
*/
virtual int32_t hashCode(void) const;
virtual int32_t hashCode() const;
/**
* Returns the description used to create this iterator
* @return the description used to create this iterator
* @stable ICU 2.0
*/
virtual const UnicodeString& getRules(void) const;
virtual const UnicodeString& getRules() const;
//=======================================================================
// BreakIterator overrides
@ -425,8 +425,7 @@ public:
* @return An iterator over the text being analyzed.
* @stable ICU 2.0
*/
virtual CharacterIterator& getText(void) const override;
virtual CharacterIterator& getText() const override;
/**
* Get a UText for the text being analyzed.
@ -486,14 +485,14 @@ public:
* @return The offset of the beginning of the text, zero.
* @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.
* @return The text's past-the-end offset.
* @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.
@ -512,14 +511,14 @@ public:
* @return The position of the first boundary after this one.
* @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.
* @return The position of the last boundary position preceding this one.
* @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
@ -557,8 +556,7 @@ public:
* @return The current iteration position.
* @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
@ -629,7 +627,7 @@ public:
* other classes have different class IDs.
* @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
@ -642,7 +640,7 @@ public:
* @return The class ID for all objects of this class.
* @stable ICU 2.0
*/
static UClassID U_EXPORT2 getStaticClassID(void);
static UClassID U_EXPORT2 getStaticClassID();
#ifndef U_FORCE_HIDE_DEPRECATED_API
/**
@ -799,7 +797,7 @@ private:
void dumpTables();
#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.
* Because ICU may choose to cache break engine internally, this must
@ -811,7 +809,7 @@ private:
*/
static void U_EXPORT2 registerExternalBreakEngine(
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.
* @stable ICU 2.0
*/
int32_t
getSize(void) const;
int32_t getSize() const;
/**
* 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
* @stable ICU 2.0
*/
UBool
hasNext(void) const;
UBool hasNext() const;
/**
* Resets the internal context of a resource so that iteration starts from the first element.
*
* @stable ICU 2.0
*/
void
resetIterator(void);
void resetIterator();
/**
* 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
* @stable ICU 2.0
*/
const char*
getKey(void) const;
const char* getKey() const;
/**
* 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
* @stable ICU 2.0
*/
const char*
getName(void) const;
const char* getName() const;
/**
* Returns the type of a resource. Available types are defined in enum UResType
@ -327,8 +321,7 @@ public:
* @return type of the given resource.
* @stable ICU 2.0
*/
UResType
getType(void) const;
UResType getType() const;
/**
* Returns the next resource in a given resource or nullptr if there are no more resources
@ -424,8 +417,7 @@ public:
* @see getVersion
* @deprecated ICU 2.8 Use getVersion instead.
*/
const char*
getVersionNumber(void) const;
const char* getVersionNumber() const;
#endif /* U_HIDE_DEPRECATED_API */
/**
@ -445,8 +437,7 @@ public:
* @return a Locale object
* @deprecated ICU 2.8 Use getLocale(ULocDataLocaleType type, UErrorCode &status) overload instead.
*/
const Locale&
getLocale(void) const;
const Locale& getLocale() const;
#endif /* U_HIDE_DEPRECATED_API */
/**

View File

@ -156,14 +156,14 @@ public:
* @return a class ID for this object.
* @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
* @stable ICU 2.0
*/
static UClassID U_EXPORT2 getStaticClassID(void);
static UClassID U_EXPORT2 getStaticClassID();
protected:
/**

View File

@ -25,11 +25,9 @@
U_NAMESPACE_BEGIN
// Forward declaration:
namespace number {
namespace impl {
namespace number::impl {
class SimpleModifier;
}
}
/**
* 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
*/
template <typename T,
typename = typename std::enable_if<
(std::is_same<decltype(T().data()), const char*>::value
typename = std::enable_if_t<
(std::is_same_v<decltype(T().data()), const char*>
#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
) &&
std::is_same<decltype(T().size()), size_t>::value>::type>
std::is_same_v<decltype(T().size()), size_t>>>
StringPiece(T str)
: ptr_(reinterpret_cast<const char*>(str.data())),
length_(static_cast<int32_t>(str.size())) {}

View File

@ -25,6 +25,7 @@
#ifndef UCHAR_H
#define UCHAR_H
#include <stdbool.h>
#include "unicode/utypes.h"
#include "unicode/stringoptions.h"
#include "unicode/ucpmap.h"
@ -668,12 +669,21 @@ typedef enum UProperty {
* @stable ICU 63
*/
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
/**
* 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.
*/
UCHAR_INT_LIMIT=0x1019,
UCHAR_INT_LIMIT=0x101A,
#endif // U_HIDE_DEPRECATED_API
/** Bitmask property General_Category_Mask.
@ -774,12 +784,28 @@ typedef enum UProperty {
UCHAR_SCRIPT_EXTENSIONS=0x7000,
/** First constant for Unicode properties with unusual value types. @stable ICU 4.6 */
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
/**
* 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.
*/
UCHAR_OTHER_PROPERTY_LIMIT=0x7001,
UCHAR_OTHER_PROPERTY_LIMIT=0x7002,
#endif // U_HIDE_DEPRECATED_API
/** Represents a nonexistent or invalid property or property value. @stable ICU 2.4 */
@ -2701,6 +2727,68 @@ typedef enum UVerticalOrientation {
U_VO_UPRIGHT,
} 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.
*
@ -3905,6 +3993,59 @@ u_isIDStart(UChar32 c);
U_CAPI UBool U_EXPORT2
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
* as an ignorable character in an identifier,

View File

@ -126,7 +126,7 @@ public:
* @return the hash code.
* @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
@ -144,7 +144,7 @@ public:
* @return the first code unit in its iteration range.
* @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
@ -154,7 +154,7 @@ public:
* @return the first code unit in its iteration range
* @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
@ -165,7 +165,7 @@ public:
* @return the first code point in its iteration range
* @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
@ -175,7 +175,7 @@ public:
* @return the first code point in its iteration range.
* @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
@ -184,7 +184,7 @@ public:
* @return the last code unit in its iteration range.
* @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
@ -193,7 +193,7 @@ public:
* @return the last code point in its iteration range.
* @stable ICU 2.0
*/
virtual UChar32 last32(void) override;
virtual UChar32 last32() override;
/**
* 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.
* @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.
* @return the code point the iterator currently refers to.
* @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
@ -239,7 +239,7 @@ public:
* @return the next code unit in the iteration range.
* @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
@ -249,7 +249,7 @@ public:
* @return the current code unit.
* @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
@ -261,7 +261,7 @@ public:
* @return the next code point in the iteration range.
* @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
@ -271,7 +271,7 @@ public:
* @return the current point.
* @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
@ -291,7 +291,7 @@ public:
* @return the previous code unit in the iteration range.
* @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
@ -300,7 +300,7 @@ public:
* @return the previous code point in the iteration range.
* @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
@ -363,14 +363,14 @@ public:
* @return a class ID for this class
* @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.
* @stable ICU 2.0
*/
virtual UClassID getDynamicClassID(void) const override;
virtual UClassID getDynamicClassID() const override;
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
* associate any meaning to these aliases.</p>
*
* \snippet samples/ucnv/convsamp.cpp ucnv_open
*
* @param converterName Name of the coded character set table.
* This may have options appended to the string.
* 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.
* <p>
* Usage:
* \snippet samples/ucnv/convsamp.cpp ucnv_detectUnicodeSignature
*
* @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.

View File

@ -413,6 +413,17 @@
# define UCONFIG_NO_FORMATTING 0
#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
* This switch turns off transliteration.

View File

@ -399,6 +399,9 @@ uloc_setDefault(const char* localeID,
/**
* 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 language the language code for localeID
* @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.
*
* 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 script the language code for localeID
* @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.
*
* 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 country the country code for localeID
* @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.
*
* 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 variant the variant code for localeID
* @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.
*
* 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
* a certain extent. Upper and lower case are set as needed.
* 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
* 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:
*
* "und_Zzzz" 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"
*
* "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 maximizedLocaleID The maximized locale

View File

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

View File

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

View File

@ -83,7 +83,7 @@ public:
* @return The class ID for all objects of this class.
* @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
@ -100,7 +100,7 @@ public:
* different class IDs.
* @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

View File

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

View File

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

View File

@ -272,6 +272,7 @@
#define u_getDataVersion U_ICU_ENTRY_POINT_RENAME(u_getDataVersion)
#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_getIDTypes U_ICU_ENTRY_POINT_RENAME(u_getIDTypes)
#define u_getISOComment U_ICU_ENTRY_POINT_RENAME(u_getISOComment)
#define u_getIntPropertyMap U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMap)
#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_get_stdout U_ICU_ENTRY_POINT_RENAME(u_get_stdout)
#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_isIDIgnorable U_ICU_ENTRY_POINT_RENAME(u_isIDIgnorable)
#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_forLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_forLanguageTag)
#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_getKeywords U_ICU_ENTRY_POINT_RENAME(ulocimp_getKeywords)
#define ulocimp_getKnownCanonicalizedLocaleForTest U_ICU_ENTRY_POINT_RENAME(ulocimp_getKnownCanonicalizedLocaleForTest)
#define ulocimp_getLanguage U_ICU_ENTRY_POINT_RENAME(ulocimp_getLanguage)
#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_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_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_toBcpType U_ICU_ENTRY_POINT_RENAME(ulocimp_toBcpType)
#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_openForInt64 U_ICU_ENTRY_POINT_RENAME(usnum_openForInt64)
#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_setMinimumIntegerDigits U_ICU_ENTRY_POINT_RENAME(usnum_setMinimumIntegerDigits)
#define usnum_setSign U_ICU_ENTRY_POINT_RENAME(usnum_setSign)

View File

@ -500,6 +500,9 @@ typedef enum UScriptCode {
/** @stable ICU 72 */
USCRIPT_NAG_MUNDARI = 199,/* Nagm */
/** @stable ICU 75 */
USCRIPT_ARABIC_NASTALIQ = 200, /* Aran */
#ifndef U_HIDE_DEPRECATED_API
/**
* 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.
*/
USCRIPT_CODE_LIMIT = 200
USCRIPT_CODE_LIMIT = 201
#endif // U_HIDE_DEPRECATED_API
} UScriptCode;

View File

@ -109,7 +109,6 @@ enum {
*/
USET_ADD_CASE_MAPPINGS = 4,
#ifndef U_HIDE_DRAFT_API
/**
* Enable case insensitive matching.
* 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,
* such as in ECMAScript (JavaScript) regular expressions.
*
* @draft ICU 73
* @stable ICU 73
*/
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