mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-22520 Standardize return on error for all locale functions.
· No function should do anything if an error has already occurred. · On error, a value of 0, nullptr, {}, etc., should be returned. · Values shouldn't have overloaded meanings (eg. index or found). · Values that are never used should not be returned at all.
This commit is contained in:
parent
35353f2d7f
commit
929cd9bb4f
17 changed files with 361 additions and 359 deletions
|
@ -203,6 +203,7 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
|
|||
void
|
||||
_clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
|
||||
{
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
// Clear Unicode attributes
|
||||
locale.setKeywordValue(kAttributeKey, "", errorCode);
|
||||
|
||||
|
@ -218,6 +219,7 @@ _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
|
|||
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);
|
||||
|
|
|
@ -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"
|
||||
|
@ -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.value()]
|
||||
: 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.value()]
|
||||
: 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.value()], 0, suppIndex.value(), 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.value()],
|
||||
lsrIter.getBestDesiredIndex(), suppIndex.value(), true);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter,
|
||||
UErrorCode &errorCode) const {
|
||||
if (U_FAILURE(errorCode)) { return -1; }
|
||||
std::optional<int32_t> LocaleMatcher::getBestSuppIndex(LSR desiredLSR,
|
||||
LocaleLsrIterator *remainingIter,
|
||||
UErrorCode &errorCode) const {
|
||||
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),
|
||||
|
|
|
@ -101,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) {
|
||||
|
@ -138,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++;
|
||||
|
||||
|
@ -170,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];
|
||||
|
|
|
@ -306,6 +306,7 @@ _getStringOrCopyKey(const char *path, const char *locale,
|
|||
const char *substitute,
|
||||
char16_t *dest, int32_t destCapacity,
|
||||
UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return 0; }
|
||||
const char16_t *s = nullptr;
|
||||
int32_t length = 0;
|
||||
|
||||
|
@ -368,14 +369,10 @@ _getDisplayNameForComponent(const char *locale,
|
|||
UDisplayNameGetter *getter,
|
||||
const char *tag,
|
||||
UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return 0; }
|
||||
UErrorCode localStatus;
|
||||
const char* root = nullptr;
|
||||
|
||||
/* argument checking */
|
||||
if (U_FAILURE(errorCode)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) {
|
||||
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
|
@ -422,6 +419,7 @@ 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,
|
||||
ulocimp_getScript, _kScriptsStandAlone, err);
|
||||
|
|
|
@ -916,6 +916,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(
|
||||
|
@ -1061,7 +1063,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
|
||||
|
@ -1126,12 +1128,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,
|
||||
|
@ -1168,8 +1170,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)
|
||||
|
@ -1587,8 +1590,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)
|
||||
|
@ -1778,6 +1782,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);
|
||||
}
|
||||
|
@ -1787,6 +1792,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) {
|
||||
|
@ -2453,7 +2460,8 @@ public:
|
|||
(int32_t)(current - keywords.data()), status);
|
||||
}
|
||||
|
||||
virtual int32_t count(UErrorCode &/*status*/) const override {
|
||||
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) {
|
||||
|
@ -2483,12 +2491,14 @@ 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 {
|
||||
virtual void reset(UErrorCode& status) override {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
current = keywords.data();
|
||||
}
|
||||
};
|
||||
|
@ -2521,7 +2531,8 @@ public:
|
|||
if (resultLength != nullptr) *resultLength = 0;
|
||||
return nullptr;
|
||||
}
|
||||
virtual int32_t count(UErrorCode &/*status*/) const override {
|
||||
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) {
|
||||
|
@ -2625,6 +2636,10 @@ 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)) {
|
||||
|
@ -2632,7 +2647,6 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName,
|
|||
}
|
||||
|
||||
const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data());
|
||||
|
||||
if (legacy_key == nullptr) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
|
@ -2705,6 +2719,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);
|
||||
|
@ -2715,16 +2730,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;
|
||||
|
|
|
@ -130,17 +130,17 @@ bool CHECK_TRAILING_VARIANT_SIZE(const char* variant, int32_t variantLength) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
_uloc_addLikelySubtags(const char* localeID,
|
||||
icu::ByteSink& sink,
|
||||
UErrorCode& err) {
|
||||
if (U_FAILURE(err)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (localeID == nullptr) {
|
||||
err = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
icu::CharString lang;
|
||||
|
@ -150,12 +150,12 @@ _uloc_addLikelySubtags(const char* localeID,
|
|||
const char* trailing = nullptr;
|
||||
ulocimp_getSubtags(localeID, &lang, &script, ®ion, &variant, &trailing, err);
|
||||
if (U_FAILURE(err)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CHECK_TRAILING_VARIANT_SIZE(variant.data(), variant.length())) {
|
||||
err = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (lang.length() > 3) {
|
||||
|
@ -164,7 +164,7 @@ _uloc_addLikelySubtags(const char* localeID,
|
|||
lang.clear();
|
||||
} else {
|
||||
err = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,18 +172,18 @@ _uloc_addLikelySubtags(const char* localeID,
|
|||
|
||||
const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err);
|
||||
if (U_FAILURE(err)) {
|
||||
return false;
|
||||
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()) {
|
||||
err = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, err);
|
||||
if (U_FAILURE(err)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
const char* language = lsr.language;
|
||||
if (uprv_strcmp(language, "und") == 0) {
|
||||
|
@ -202,16 +202,8 @@ _uloc_addLikelySubtags(const char* localeID,
|
|||
trailingLength,
|
||||
sink,
|
||||
err);
|
||||
|
||||
return U_SUCCESS(err);
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool _ulocimp_addLikelySubtags(const char*, icu::ByteSink&, UErrorCode&);
|
||||
|
||||
void
|
||||
_uloc_minimizeSubtags(const char* localeID,
|
||||
icu::ByteSink& sink,
|
||||
|
@ -290,12 +282,12 @@ uloc_addLikelySubtags(const char* localeID,
|
|||
maximizedLocaleID, maximizedLocaleIDCapacity);
|
||||
|
||||
ulocimp_addLikelySubtags(localeID, sink, *status);
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return sink.Overflowed() ? reslen : -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -306,29 +298,17 @@ uloc_addLikelySubtags(const char* localeID,
|
|||
return reslen;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool
|
||||
_ulocimp_addLikelySubtags(const char* localeID,
|
||||
icu::ByteSink& sink,
|
||||
UErrorCode& status) {
|
||||
U_EXPORT void
|
||||
ulocimp_addLikelySubtags(const char* localeID,
|
||||
icu::ByteSink& sink,
|
||||
UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
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;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
U_EXPORT void
|
||||
ulocimp_addLikelySubtags(const char* localeID,
|
||||
icu::ByteSink& sink,
|
||||
UErrorCode& status) {
|
||||
_ulocimp_addLikelySubtags(localeID, sink, status);
|
||||
_uloc_addLikelySubtags(localeBuffer.data(), sink, status);
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
|
@ -344,12 +324,12 @@ uloc_minimizeSubtags(const char* localeID,
|
|||
minimizedLocaleID, minimizedLocaleIDCapacity);
|
||||
|
||||
ulocimp_minimizeSubtags(localeID, sink, false, *status);
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return sink.Overflowed() ? reslen : -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -365,6 +345,7 @@ ulocimp_minimizeSubtags(const char* localeID,
|
|||
icu::ByteSink& sink,
|
||||
bool favorScript,
|
||||
UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
icu::CharString localeBuffer;
|
||||
{
|
||||
icu::CharStringByteSink localeSink(&localeBuffer);
|
||||
|
|
|
@ -70,6 +70,7 @@ struct LikelySubtagsData {
|
|||
}
|
||||
|
||||
void load(UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
StackUResourceBundle stackTempBundle;
|
||||
|
@ -230,6 +231,7 @@ struct LikelySubtagsData {
|
|||
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; }
|
||||
|
@ -296,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;
|
||||
|
@ -314,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; }
|
||||
|
@ -380,6 +383,7 @@ constexpr const char16_t* MACROREGION_HARDCODE[] = {
|
|||
|
||||
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);
|
||||
|
@ -399,6 +403,7 @@ void processMacroregionRange(const UnicodeString& regionName, UVector* newMacroR
|
|||
|
||||
#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));
|
||||
|
@ -423,6 +428,7 @@ UVector* loadMacroregions(UErrorCode &status) {
|
|||
#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)) {
|
||||
|
@ -515,9 +521,10 @@ LikelySubtags::~LikelySubtags() {
|
|||
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=")
|
||||
|
@ -553,6 +560,7 @@ LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, co
|
|||
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.
|
||||
|
@ -607,6 +615,7 @@ LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, co
|
|||
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)},
|
||||
|
@ -615,10 +624,10 @@ LSR LikelySubtags::maximize(const char *language, const char *script, const char
|
|||
}
|
||||
|
||||
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, &LikelySubtags::initLikelySubtags, errorCode);
|
||||
if (U_FAILURE(errorCode)) { return false; }
|
||||
UnicodeString str(UnicodeString::fromUTF8(region));
|
||||
|
@ -628,9 +637,7 @@ bool LikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) co
|
|||
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 = "";
|
||||
}
|
||||
|
@ -920,10 +927,9 @@ 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 &&
|
||||
|
@ -936,9 +942,7 @@ LSR LikelySubtags::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);
|
||||
}
|
||||
|
@ -947,27 +951,21 @@ LSR LikelySubtags::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);
|
||||
}
|
||||
|
|
|
@ -977,6 +977,7 @@ idCmp(const char* id1, const char* id2)
|
|||
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);
|
||||
|
@ -1004,7 +1005,7 @@ getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status)
|
|||
|
||||
/*no match found */
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return this_0->regionMaps->hostID;
|
||||
return locmap_root->hostID;
|
||||
}
|
||||
|
||||
const char*
|
||||
|
@ -1151,7 +1152,7 @@ uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UEr
|
|||
|
||||
/* no match found */
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1257,6 +1258,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;
|
||||
|
@ -1270,11 +1279,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*/{
|
||||
|
@ -1319,5 +1323,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) */
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ 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;
|
||||
|
@ -159,45 +160,47 @@ _uloc_getOrientationHelper(const char* localeId,
|
|||
{
|
||||
ULayoutType result = ULOC_LAYOUT_UNKNOWN;
|
||||
|
||||
if (!U_FAILURE(status)) {
|
||||
icu::CharString localeBuffer;
|
||||
if (U_FAILURE(status)) { return result; }
|
||||
|
||||
icu::CharString localeBuffer;
|
||||
{
|
||||
icu::CharStringByteSink sink(&localeBuffer);
|
||||
ulocimp_canonicalize(localeId, sink, status);
|
||||
}
|
||||
|
||||
if (U_FAILURE(status)) { return result; }
|
||||
|
||||
int32_t length = 0;
|
||||
const char16_t* const value =
|
||||
uloc_getTableStringWithFallback(
|
||||
nullptr,
|
||||
localeBuffer.data(),
|
||||
"layout",
|
||||
nullptr,
|
||||
key,
|
||||
&length,
|
||||
&status);
|
||||
|
||||
if (U_FAILURE(status)) { return result; }
|
||||
|
||||
if (length != 0) {
|
||||
switch(value[0])
|
||||
{
|
||||
icu::CharStringByteSink sink(&localeBuffer);
|
||||
ulocimp_canonicalize(localeId, sink, status);
|
||||
}
|
||||
|
||||
if (!U_FAILURE(status)) {
|
||||
int32_t length = 0;
|
||||
const char16_t* const value =
|
||||
uloc_getTableStringWithFallback(
|
||||
nullptr,
|
||||
localeBuffer.data(),
|
||||
"layout",
|
||||
nullptr,
|
||||
key,
|
||||
&length,
|
||||
&status);
|
||||
|
||||
if (!U_FAILURE(status) && length != 0) {
|
||||
switch(value[0])
|
||||
{
|
||||
case 0x0062: /* 'b' */
|
||||
result = ULOC_LAYOUT_BTT;
|
||||
break;
|
||||
case 0x006C: /* 'l' */
|
||||
result = ULOC_LAYOUT_LTR;
|
||||
break;
|
||||
case 0x0072: /* 'r' */
|
||||
result = ULOC_LAYOUT_RTL;
|
||||
break;
|
||||
case 0x0074: /* 't' */
|
||||
result = ULOC_LAYOUT_TTB;
|
||||
break;
|
||||
default:
|
||||
status = U_INTERNAL_PROGRAM_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 0x0062: /* 'b' */
|
||||
result = ULOC_LAYOUT_BTT;
|
||||
break;
|
||||
case 0x006C: /* 'l' */
|
||||
result = ULOC_LAYOUT_LTR;
|
||||
break;
|
||||
case 0x0072: /* 'r' */
|
||||
result = ULOC_LAYOUT_RTL;
|
||||
break;
|
||||
case 0x0074: /* 't' */
|
||||
result = ULOC_LAYOUT_TTB;
|
||||
break;
|
||||
default:
|
||||
status = U_INTERNAL_PROGRAM_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -553,17 +553,19 @@ namespace {
|
|||
*/
|
||||
CharString locale_canonKeywordName(const char* keywordName, UErrorCode& status)
|
||||
{
|
||||
if (U_FAILURE(status)) { return {}; }
|
||||
CharString result;
|
||||
|
||||
for (; *keywordName != 0; keywordName++) {
|
||||
if (!UPRV_ISALPHANUM(*keywordName)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
|
||||
return result;
|
||||
return {};
|
||||
}
|
||||
result.append(uprv_tolower(*keywordName), status);
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name */
|
||||
return {};
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -592,6 +594,8 @@ ulocimp_getKeywords(const char* localeID,
|
|||
bool valuesToo,
|
||||
UErrorCode& status)
|
||||
{
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
KeywordStruct keywordList[ULOC_MAX_NO_KEYWORDS];
|
||||
|
||||
int32_t maxKeywords = ULOC_MAX_NO_KEYWORDS;
|
||||
|
@ -718,13 +722,12 @@ uloc_getKeywordValue(const char* localeID,
|
|||
|
||||
CheckedArrayByteSink sink(buffer, bufferCapacity);
|
||||
ulocimp_getKeywordValue(localeID, keywordName, sink, *status);
|
||||
if (U_FAILURE(*status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return reslen;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -740,102 +743,102 @@ ulocimp_getKeywordValue(const char* localeID,
|
|||
icu::ByteSink& sink,
|
||||
UErrorCode& status)
|
||||
{
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
if (localeID == nullptr || keywordName == nullptr || keywordName[0] == 0) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
const char* startSearchHere = nullptr;
|
||||
const char* nextSeparator = nullptr;
|
||||
|
||||
if (localeID != nullptr && U_SUCCESS(status)) {
|
||||
CharString tempBuffer;
|
||||
const char* tmpLocaleID;
|
||||
CharString tempBuffer;
|
||||
const char* tmpLocaleID;
|
||||
|
||||
if (keywordName == nullptr || keywordName[0] == 0) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
CharString canonKeywordName = locale_canonKeywordName(keywordName, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hasBCP47Extension(localeID)) {
|
||||
CharStringByteSink sink(&tempBuffer);
|
||||
ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status);
|
||||
tmpLocaleID = U_SUCCESS(status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID;
|
||||
} else {
|
||||
tmpLocaleID=localeID;
|
||||
}
|
||||
|
||||
startSearchHere = locale_getKeywordsStart(tmpLocaleID);
|
||||
if(startSearchHere == nullptr) {
|
||||
/* no keywords, return at once */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CharString canonKeywordName = locale_canonKeywordName(keywordName, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
/* find the first keyword */
|
||||
while(startSearchHere) {
|
||||
const char* keyValueTail;
|
||||
|
||||
if (_hasBCP47Extension(localeID)) {
|
||||
CharStringByteSink sink(&tempBuffer);
|
||||
ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status);
|
||||
tmpLocaleID = U_SUCCESS(status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID;
|
||||
} else {
|
||||
tmpLocaleID=localeID;
|
||||
}
|
||||
|
||||
startSearchHere = locale_getKeywordsStart(tmpLocaleID);
|
||||
if(startSearchHere == nullptr) {
|
||||
/* no keywords, return at once */
|
||||
return;
|
||||
}
|
||||
|
||||
/* find the first keyword */
|
||||
while(startSearchHere) {
|
||||
const char* keyValueTail;
|
||||
|
||||
startSearchHere++; /* skip @ or ; */
|
||||
nextSeparator = uprv_strchr(startSearchHere, '=');
|
||||
if(!nextSeparator) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */
|
||||
return;
|
||||
startSearchHere++; /* skip @ or ; */
|
||||
nextSeparator = uprv_strchr(startSearchHere, '=');
|
||||
if(!nextSeparator) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */
|
||||
return;
|
||||
}
|
||||
/* strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*startSearchHere == ' ') {
|
||||
startSearchHere++;
|
||||
}
|
||||
keyValueTail = nextSeparator;
|
||||
while (keyValueTail > startSearchHere && *(keyValueTail-1) == ' ') {
|
||||
keyValueTail--;
|
||||
}
|
||||
/* now keyValueTail points to first char after the keyName */
|
||||
/* copy & normalize keyName from locale */
|
||||
if (startSearchHere == keyValueTail) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */
|
||||
return;
|
||||
}
|
||||
CharString localeKeywordName;
|
||||
while (startSearchHere < keyValueTail) {
|
||||
if (!UPRV_ISALPHANUM(*startSearchHere)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
|
||||
return;
|
||||
}
|
||||
/* strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*startSearchHere == ' ') {
|
||||
startSearchHere++;
|
||||
}
|
||||
keyValueTail = nextSeparator;
|
||||
while (keyValueTail > startSearchHere && *(keyValueTail-1) == ' ') {
|
||||
localeKeywordName.append(uprv_tolower(*startSearchHere++), status);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
startSearchHere = uprv_strchr(nextSeparator, ';');
|
||||
|
||||
if (canonKeywordName == localeKeywordName) {
|
||||
/* current entry matches the keyword. */
|
||||
nextSeparator++; /* skip '=' */
|
||||
/* First strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*nextSeparator == ' ') {
|
||||
nextSeparator++;
|
||||
}
|
||||
keyValueTail = (startSearchHere)? startSearchHere: nextSeparator + uprv_strlen(nextSeparator);
|
||||
while(keyValueTail > nextSeparator && *(keyValueTail-1) == ' ') {
|
||||
keyValueTail--;
|
||||
}
|
||||
/* now keyValueTail points to first char after the keyName */
|
||||
/* copy & normalize keyName from locale */
|
||||
if (startSearchHere == keyValueTail) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */
|
||||
return;
|
||||
}
|
||||
CharString localeKeywordName;
|
||||
while (startSearchHere < keyValueTail) {
|
||||
if (!UPRV_ISALPHANUM(*startSearchHere)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
|
||||
}
|
||||
/* Now copy the value, but check well-formedness */
|
||||
if (nextSeparator == keyValueTail) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value name in passed-in locale */
|
||||
return;
|
||||
}
|
||||
localeKeywordName.append(uprv_tolower(*startSearchHere++), status);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
startSearchHere = uprv_strchr(nextSeparator, ';');
|
||||
|
||||
if (canonKeywordName == localeKeywordName) {
|
||||
/* current entry matches the keyword. */
|
||||
nextSeparator++; /* skip '=' */
|
||||
/* First strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*nextSeparator == ' ') {
|
||||
nextSeparator++;
|
||||
}
|
||||
keyValueTail = (startSearchHere)? startSearchHere: nextSeparator + uprv_strlen(nextSeparator);
|
||||
while(keyValueTail > nextSeparator && *(keyValueTail-1) == ' ') {
|
||||
keyValueTail--;
|
||||
}
|
||||
/* Now copy the value, but check well-formedness */
|
||||
if (nextSeparator == keyValueTail) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value name in passed-in locale */
|
||||
while (nextSeparator < keyValueTail) {
|
||||
if (!UPRV_ISALPHANUM(*nextSeparator) && !UPRV_OK_VALUE_PUNCTUATION(*nextSeparator)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */
|
||||
return;
|
||||
}
|
||||
while (nextSeparator < keyValueTail) {
|
||||
if (!UPRV_ISALPHANUM(*nextSeparator) && !UPRV_OK_VALUE_PUNCTUATION(*nextSeparator)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */
|
||||
return;
|
||||
}
|
||||
/* Should we lowercase value to return here? Tests expect as-is. */
|
||||
sink.Append(nextSeparator++, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Should we lowercase value to return here? Tests expect as-is. */
|
||||
sink.Append(nextSeparator++, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -845,9 +848,7 @@ uloc_setKeywordValue(const char* keywordName,
|
|||
char* buffer, int32_t bufferCapacity,
|
||||
UErrorCode* status)
|
||||
{
|
||||
if (U_FAILURE(*status)) {
|
||||
return -1;
|
||||
}
|
||||
if (U_FAILURE(*status)) { return 0; }
|
||||
|
||||
if (bufferCapacity <= 1) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -870,8 +871,7 @@ uloc_setKeywordValue(const char* keywordName,
|
|||
keywords, keywordName, keywordValue, sink, *status);
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
// A positive return value is a length, otherwise it's an error code.
|
||||
return reslen > 0 ? reslen + baseLen : reslen;
|
||||
return *status == U_BUFFER_OVERFLOW_ERROR ? reslen + baseLen : 0;
|
||||
}
|
||||
|
||||
// See the documentation for this function, it's guaranteed to never
|
||||
|
@ -904,6 +904,8 @@ ulocimp_setKeywordValue(const char* keywords,
|
|||
ByteSink& sink,
|
||||
UErrorCode& status)
|
||||
{
|
||||
if (U_FAILURE(status)) { return 0; }
|
||||
|
||||
/* TODO: sorting. removal. */
|
||||
int32_t needLen = 0;
|
||||
int32_t rc;
|
||||
|
@ -914,9 +916,6 @@ ulocimp_setKeywordValue(const char* keywords,
|
|||
bool handledInputKeyAndValue = false;
|
||||
char keyValuePrefix = '@';
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return -1;
|
||||
}
|
||||
if (status == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
|
@ -1132,7 +1131,7 @@ inline bool _isBCP47Extension(const char* p) {
|
|||
* The 'list' param should be LANGUAGES, LANGUAGES_3, COUNTRIES, or
|
||||
* COUNTRIES_3.
|
||||
*/
|
||||
int16_t _findIndex(const char* const* list, const char* key)
|
||||
std::optional<int16_t> _findIndex(const char* const* list, const char* key)
|
||||
{
|
||||
const char* const* anchor = list;
|
||||
int32_t pass = 0;
|
||||
|
@ -1147,26 +1146,20 @@ int16_t _findIndex(const char* const* list, const char* key)
|
|||
}
|
||||
++list; /* skip final nullptr *CWB*/
|
||||
}
|
||||
return -1;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
U_CFUNC const char*
|
||||
uloc_getCurrentCountryID(const char* oldID){
|
||||
int32_t offset = _findIndex(DEPRECATED_COUNTRIES, oldID);
|
||||
if (offset >= 0) {
|
||||
return REPLACEMENT_COUNTRIES[offset];
|
||||
}
|
||||
return oldID;
|
||||
std::optional<int16_t> offset = _findIndex(DEPRECATED_COUNTRIES, oldID);
|
||||
return offset.has_value() ? REPLACEMENT_COUNTRIES[offset.value()] : oldID;
|
||||
}
|
||||
U_CFUNC const char*
|
||||
uloc_getCurrentLanguageID(const char* oldID){
|
||||
int32_t offset = _findIndex(DEPRECATED_LANGUAGES, oldID);
|
||||
if (offset >= 0) {
|
||||
return REPLACEMENT_LANGUAGES[offset];
|
||||
}
|
||||
return oldID;
|
||||
std::optional<int16_t> offset = _findIndex(DEPRECATED_LANGUAGES, oldID);
|
||||
return offset.has_value() ? REPLACEMENT_LANGUAGES[offset.value()] : oldID;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -1230,9 +1223,9 @@ _getLanguage(const char* localeID,
|
|||
/* convert 3 character code to 2 character code if possible *CWB*/
|
||||
U_ASSERT(capacity >= 4);
|
||||
buffer[3] = '\0';
|
||||
int32_t offset = _findIndex(LANGUAGES_3, buffer);
|
||||
if(offset>=0) {
|
||||
const char* const alias = LANGUAGES[offset];
|
||||
std::optional<int16_t> offset = _findIndex(LANGUAGES_3, buffer);
|
||||
if (offset.has_value()) {
|
||||
const char* const alias = LANGUAGES[offset.value()];
|
||||
sink->Append(alias, (int32_t)uprv_strlen(alias));
|
||||
return;
|
||||
}
|
||||
|
@ -1311,9 +1304,9 @@ _getRegion(const char* localeID,
|
|||
/* convert 3 character code to 2 character code if possible *CWB*/
|
||||
U_ASSERT(capacity >= 4);
|
||||
buffer[3] = '\0';
|
||||
int32_t offset = _findIndex(COUNTRIES_3, buffer);
|
||||
if(offset>=0) {
|
||||
const char* const alias = COUNTRIES[offset];
|
||||
std::optional<int16_t> offset = _findIndex(COUNTRIES_3, buffer);
|
||||
if (offset.has_value()) {
|
||||
const char* const alias = COUNTRIES[offset.value()];
|
||||
sink->Append(alias, (int32_t)uprv_strlen(alias));
|
||||
return;
|
||||
}
|
||||
|
@ -1387,6 +1380,7 @@ _getVariant(const char* localeID,
|
|||
|
||||
U_EXPORT CharString
|
||||
ulocimp_getLanguage(const char* localeID, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return {}; }
|
||||
CharString language;
|
||||
CharStringByteSink sink(&language);
|
||||
ulocimp_getSubtags(
|
||||
|
@ -1402,6 +1396,7 @@ ulocimp_getLanguage(const char* localeID, UErrorCode& status) {
|
|||
|
||||
U_EXPORT CharString
|
||||
ulocimp_getScript(const char* localeID, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return {}; }
|
||||
CharString script;
|
||||
CharStringByteSink sink(&script);
|
||||
ulocimp_getSubtags(
|
||||
|
@ -1417,6 +1412,7 @@ ulocimp_getScript(const char* localeID, UErrorCode& status) {
|
|||
|
||||
U_EXPORT CharString
|
||||
ulocimp_getRegion(const char* localeID, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return {}; }
|
||||
CharString region;
|
||||
CharStringByteSink sink(®ion);
|
||||
ulocimp_getSubtags(
|
||||
|
@ -1432,6 +1428,7 @@ ulocimp_getRegion(const char* localeID, UErrorCode& status) {
|
|||
|
||||
U_EXPORT CharString
|
||||
ulocimp_getVariant(const char* localeID, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return {}; }
|
||||
CharString variant;
|
||||
CharStringByteSink sink(&variant);
|
||||
ulocimp_getSubtags(
|
||||
|
@ -1454,6 +1451,8 @@ ulocimp_getSubtags(
|
|||
CharString* variant,
|
||||
const char** pEnd,
|
||||
UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
std::optional<CharStringByteSink> languageSink;
|
||||
std::optional<CharStringByteSink> scriptSink;
|
||||
std::optional<CharStringByteSink> regionSink;
|
||||
|
@ -1619,12 +1618,11 @@ static const UEnumeration gKeywordsEnum = {
|
|||
U_CAPI UEnumeration* U_EXPORT2
|
||||
uloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status)
|
||||
{
|
||||
if (U_FAILURE(*status)) { return nullptr; }
|
||||
|
||||
LocalMemory<UKeywordsContext> myContext;
|
||||
LocalMemory<UEnumeration> result;
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return nullptr;
|
||||
}
|
||||
myContext.adoptInstead(static_cast<UKeywordsContext *>(uprv_malloc(sizeof(UKeywordsContext))));
|
||||
result.adoptInstead(static_cast<UEnumeration *>(uprv_malloc(sizeof(UEnumeration))));
|
||||
if (myContext.isNull() || result.isNull()) {
|
||||
|
@ -1648,13 +1646,13 @@ U_CAPI UEnumeration* U_EXPORT2
|
|||
uloc_openKeywords(const char* localeID,
|
||||
UErrorCode* status)
|
||||
{
|
||||
CharString tempBuffer;
|
||||
const char* tmpLocaleID;
|
||||
|
||||
if(status==nullptr || U_FAILURE(*status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CharString tempBuffer;
|
||||
const char* tmpLocaleID;
|
||||
|
||||
if (_hasBCP47Extension(localeID)) {
|
||||
CharStringByteSink sink(&tempBuffer);
|
||||
ulocimp_forLanguageTag(localeID, -1, sink, nullptr, *status);
|
||||
|
@ -1889,13 +1887,12 @@ uloc_getParent(const char* localeID,
|
|||
|
||||
CheckedArrayByteSink sink(parent, parentCapacity);
|
||||
ulocimp_getParent(localeID, sink, *err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return reslen;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -1910,12 +1907,11 @@ ulocimp_getParent(const char* localeID,
|
|||
icu::ByteSink& sink,
|
||||
UErrorCode& err)
|
||||
{
|
||||
if (U_FAILURE(err)) { return; }
|
||||
|
||||
const char *lastUnderscore;
|
||||
int32_t i;
|
||||
|
||||
if (U_FAILURE(err))
|
||||
return;
|
||||
|
||||
if (localeID == nullptr)
|
||||
localeID = uloc_getDefault();
|
||||
|
||||
|
@ -1956,13 +1952,12 @@ uloc_getLanguage(const char* localeID,
|
|||
nullptr,
|
||||
nullptr,
|
||||
*err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t length = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return length;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
return length;
|
||||
|
@ -1990,13 +1985,12 @@ uloc_getScript(const char* localeID,
|
|||
nullptr,
|
||||
nullptr,
|
||||
*err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t length = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return length;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
return length;
|
||||
|
@ -2024,13 +2018,12 @@ uloc_getCountry(const char* localeID,
|
|||
nullptr,
|
||||
nullptr,
|
||||
*err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t length = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return length;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
return length;
|
||||
|
@ -2058,13 +2051,12 @@ uloc_getVariant(const char* localeID,
|
|||
&sink,
|
||||
nullptr,
|
||||
*err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t length = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return length;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
return length;
|
||||
|
@ -2085,13 +2077,12 @@ uloc_getName(const char* localeID,
|
|||
|
||||
CheckedArrayByteSink sink(name, nameCapacity);
|
||||
ulocimp_getName(localeID, sink, *err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return reslen;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -2121,13 +2112,12 @@ uloc_getBaseName(const char* localeID,
|
|||
|
||||
CheckedArrayByteSink sink(name, nameCapacity);
|
||||
ulocimp_getBaseName(localeID, sink, *err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return reslen;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -2157,13 +2147,12 @@ uloc_canonicalize(const char* localeID,
|
|||
|
||||
CheckedArrayByteSink sink(name, nameCapacity);
|
||||
ulocimp_canonicalize(localeID, sink, *err);
|
||||
if (U_FAILURE(*err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return reslen;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -2184,7 +2173,6 @@ ulocimp_canonicalize(const char* localeID,
|
|||
U_CAPI const char* U_EXPORT2
|
||||
uloc_getISO3Language(const char* localeID)
|
||||
{
|
||||
int16_t offset;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
if (localeID == nullptr)
|
||||
|
@ -2194,16 +2182,13 @@ uloc_getISO3Language(const char* localeID)
|
|||
CharString lang = ulocimp_getLanguage(localeID, err);
|
||||
if (U_FAILURE(err))
|
||||
return "";
|
||||
offset = _findIndex(LANGUAGES, lang.data());
|
||||
if (offset < 0)
|
||||
return "";
|
||||
return LANGUAGES_3[offset];
|
||||
std::optional<int16_t> offset = _findIndex(LANGUAGES, lang.data());
|
||||
return offset.has_value() ? LANGUAGES_3[offset.value()] : "";
|
||||
}
|
||||
|
||||
U_CAPI const char* U_EXPORT2
|
||||
uloc_getISO3Country(const char* localeID)
|
||||
{
|
||||
int16_t offset;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
if (localeID == nullptr)
|
||||
|
@ -2213,11 +2198,8 @@ uloc_getISO3Country(const char* localeID)
|
|||
CharString cntry = ulocimp_getRegion(localeID, err);
|
||||
if (U_FAILURE(err))
|
||||
return "";
|
||||
offset = _findIndex(COUNTRIES, cntry.data());
|
||||
if (offset < 0)
|
||||
return "";
|
||||
|
||||
return COUNTRIES_3[offset];
|
||||
std::optional<int16_t> offset = _findIndex(COUNTRIES, cntry.data());
|
||||
return offset.has_value() ? COUNTRIES_3[offset.value()] : "";
|
||||
}
|
||||
|
||||
U_CAPI uint32_t U_EXPORT2
|
||||
|
|
|
@ -1169,12 +1169,9 @@ void _sortVariants(VariantListEntry* first) {
|
|||
|
||||
void
|
||||
_appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool& hadPosix, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus);
|
||||
if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
if (strict) {
|
||||
|
@ -1280,6 +1277,8 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str
|
|||
|
||||
void
|
||||
_appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool hadPosix, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
icu::MemoryPool<AttributeListEntry> attrPool;
|
||||
icu::MemoryPool<ExtensionListEntry> extPool;
|
||||
icu::MemoryPool<icu::CharString> strPool;
|
||||
|
@ -1522,6 +1521,8 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str
|
|||
*/
|
||||
void
|
||||
_appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendTo, icu::MemoryPool<ExtensionListEntry>& extPool, icu::MemoryPool<icu::CharString>& kwdBuf, bool& posixVariant, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
const char *pTag; /* beginning of current subtag */
|
||||
const char *pKwds; /* beginning of key-type pairs */
|
||||
bool variantExists = posixVariant;
|
||||
|
@ -1782,6 +1783,8 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT
|
|||
|
||||
void
|
||||
_appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
int32_t i, n;
|
||||
int32_t len;
|
||||
ExtensionListEntry *kwdFirst = nullptr;
|
||||
|
@ -1791,10 +1794,6 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status)
|
|||
icu::MemoryPool<icu::CharString> kwdBuf;
|
||||
bool posixVariant = false;
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
n = ultag_getExtensionsSize(langtag);
|
||||
|
||||
/* resolve locale keywords and reordering keys */
|
||||
|
@ -1877,14 +1876,10 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status)
|
|||
}
|
||||
|
||||
void
|
||||
_appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool hadPosix, UErrorCode& status) {
|
||||
(void)hadPosix;
|
||||
_appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool /*hadPosix*/, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus);
|
||||
if (U_FAILURE(tmpStatus)) {
|
||||
if (strict) {
|
||||
|
@ -1986,6 +1981,8 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool s
|
|||
|
||||
ULanguageTag*
|
||||
ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return nullptr; }
|
||||
|
||||
char *tagBuf;
|
||||
int16_t next;
|
||||
char *pSubtag, *pNext, *pLastGoodPosition;
|
||||
|
@ -2001,10 +1998,6 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta
|
|||
*parsedLen = 0;
|
||||
}
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (tagLen < 0) {
|
||||
tagLen = (int32_t)uprv_strlen(tag);
|
||||
}
|
||||
|
@ -2583,13 +2576,12 @@ uloc_toLanguageTag(const char* localeID,
|
|||
|
||||
icu::CheckedArrayByteSink sink(langtag, langtagCapacity);
|
||||
ulocimp_toLanguageTag(localeID, sink, strict, *status);
|
||||
if (U_FAILURE(*status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return reslen;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -2605,6 +2597,8 @@ ulocimp_toLanguageTag(const char* localeID,
|
|||
icu::ByteSink& sink,
|
||||
bool strict,
|
||||
UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
icu::CharString canonical;
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
bool hadPosix = false;
|
||||
|
@ -2684,13 +2678,12 @@ uloc_forLanguageTag(const char* langtag,
|
|||
|
||||
icu::CheckedArrayByteSink sink(localeID, localeIDCapacity);
|
||||
ulocimp_forLanguageTag(langtag, -1, sink, parsedLength, *status);
|
||||
if (U_FAILURE(*status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return reslen;
|
||||
}
|
||||
|
||||
if (sink.Overflowed()) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
@ -2707,6 +2700,8 @@ ulocimp_forLanguageTag(const char* langtag,
|
|||
icu::ByteSink& sink,
|
||||
int32_t* parsedLength,
|
||||
UErrorCode& status) {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
|
||||
bool isEmpty = true;
|
||||
const char *subtag, *p;
|
||||
int32_t len;
|
||||
|
|
|
@ -19,15 +19,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());
|
||||
}
|
||||
|
||||
|
@ -57,10 +59,10 @@ int32_t ulocale_get ##N ( \
|
|||
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; \
|
||||
return 0; \
|
||||
} \
|
||||
int32_t reslen = sink.NumberOfBytesAppended(); \
|
||||
if (sink.Overflowed()) { \
|
||||
*err = U_BUFFER_OVERFLOW_ERROR; \
|
||||
} else { \
|
||||
|
|
|
@ -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,18 +128,17 @@ 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;
|
||||
if (U_FAILURE(*err)) { return 0; }
|
||||
CheckedArrayByteSink sink(buffer, bufferCapacity);
|
||||
l.toLanguageTag(sink, *err);
|
||||
if (U_FAILURE(*err)) { return 0; }
|
||||
int32_t reslen = sink.NumberOfBytesAppended();
|
||||
if (U_FAILURE(*err)) {
|
||||
return reslen;
|
||||
}
|
||||
if (sink.Overflowed()) {
|
||||
*err = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/stringpiece.h"
|
||||
#include "unicode/uobject.h"
|
||||
|
@ -678,7 +680,7 @@ 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 LikelySubtags &likelySubtags;
|
||||
const LocaleDistance &localeDistance;
|
||||
|
|
|
@ -1183,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);
|
||||
|
@ -1222,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;
|
||||
|
@ -1239,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;
|
||||
|
@ -1256,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);
|
||||
|
@ -1265,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);
|
||||
|
|
|
@ -201,6 +201,8 @@ ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type,
|
|||
namespace {
|
||||
|
||||
UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
|
||||
if (U_FAILURE(*status)) { return nullptr; }
|
||||
|
||||
UResourceBundle *rb;
|
||||
UResourceBundle *measTypeBundle = nullptr;
|
||||
|
||||
|
@ -279,6 +281,7 @@ ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UEr
|
|||
|
||||
U_CAPI void U_EXPORT2
|
||||
ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) {
|
||||
if (U_FAILURE(*status)) { return; }
|
||||
UResourceBundle *rb = nullptr;
|
||||
rb = ures_openDirect(nullptr, "supplementalData", status);
|
||||
ures_getVersionByKey(rb, "cldrVersion", versionArray, status);
|
||||
|
|
|
@ -5946,19 +5946,19 @@ const errorData maximizeErrors[] = {
|
|||
"enfueiujhytdf",
|
||||
NULL,
|
||||
U_ILLEGAL_ARGUMENT_ERROR,
|
||||
-1
|
||||
0
|
||||
},
|
||||
{
|
||||
"en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
|
||||
NULL,
|
||||
U_ILLEGAL_ARGUMENT_ERROR,
|
||||
-1
|
||||
0
|
||||
},
|
||||
{
|
||||
"en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
|
||||
NULL,
|
||||
U_ILLEGAL_ARGUMENT_ERROR,
|
||||
-1
|
||||
0
|
||||
},
|
||||
{
|
||||
"en_Latn_US_POSIX@currency=EURO",
|
||||
|
@ -5979,13 +5979,13 @@ const errorData minimizeErrors[] = {
|
|||
"enfueiujhytdf",
|
||||
NULL,
|
||||
U_ILLEGAL_ARGUMENT_ERROR,
|
||||
-1
|
||||
0
|
||||
},
|
||||
{
|
||||
"en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
|
||||
NULL,
|
||||
U_ILLEGAL_ARGUMENT_ERROR,
|
||||
-1
|
||||
0
|
||||
},
|
||||
{
|
||||
"en_Latn_US_POSIX@currency=EURO",
|
||||
|
@ -6010,7 +6010,7 @@ static int32_t getExpectedReturnValue(const errorData* data)
|
|||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue