@@ -1957,6 +1957,7 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
1957
1957
} else {
1958
1958
fieldLen[fieldIdx - 1 ] = length - static_cast <int32_t >(field[fieldIdx - 1 ] - fullName);
1959
1959
}
1960
+ bool hasKeywords = at != nullptr && uprv_strchr (at + 1 , ' =' ) != nullptr ;
1960
1961
1961
1962
if (fieldLen[0 ] >= ULOC_LANG_CAPACITY)
1962
1963
{
@@ -1987,9 +1988,14 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
1987
1988
if (fieldLen[variantField] > 0 ) {
1988
1989
/* We have a variant */
1989
1990
variantBegin = static_cast <int32_t >(field[variantField] - fullName);
1991
+ } else if (hasKeywords) {
1992
+ // The original computation of variantBegin leaves it equal to the length
1993
+ // of fullName if there is no variant. It should instead be
1994
+ // the length of the baseName.
1995
+ variantBegin = static_cast <int32_t >(at - fullName);
1990
1996
}
1991
1997
1992
- if (Nest::fits (length, language, script, region)) {
1998
+ if (!hasKeywords && Nest::fits (length, language, script, region)) {
1993
1999
U_ASSERT (fullName == nest.baseName );
1994
2000
U_ASSERT (fullNameBuffer.isEmpty ());
1995
2001
nest.init (language, script, region, variantBegin);
@@ -2008,11 +2014,14 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
2008
2014
}
2009
2015
U_ASSERT (!fullNameBuffer.isEmpty ());
2010
2016
heap->fullName = std::move (fullNameBuffer);
2011
- }
2012
-
2013
- initBaseName (err);
2014
- if (U_FAILURE (err)) {
2015
- break ;
2017
+ if (hasKeywords) {
2018
+ if (std::string_view::size_type baseNameLength = at - fullName; baseNameLength > 0 ) {
2019
+ heap->baseName = {heap->fullName .data (), baseNameLength};
2020
+ if (heap->baseName .isEmpty ()) {
2021
+ break ; // error: out of memory
2022
+ }
2023
+ }
2024
+ }
2016
2025
}
2017
2026
2018
2027
if (canonicalize) {
@@ -2040,77 +2049,6 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
2040
2049
return *this ;
2041
2050
}
2042
2051
2043
- /*
2044
- * Set up the base name.
2045
- * If there are no key words, it's exactly the full name.
2046
- * If key words exist, it's the full name truncated at the '@' character.
2047
- * Need to set up both at init() and after setting a keyword.
2048
- */
2049
- void
2050
- Locale::initBaseName (UErrorCode &status) {
2051
- if (U_FAILURE (status)) {
2052
- return ;
2053
- }
2054
- U_ASSERT (!isBogus ());
2055
-
2056
- std::unique_ptr<Heap>* heap = std::get_if<std::unique_ptr<Heap>>(&payload);
2057
- if (heap != nullptr && *heap && !(*heap)->baseName .isEmpty ()) {
2058
- return ;
2059
- }
2060
-
2061
- const char *fullName = getName ();
2062
- const char *atPtr = uprv_strchr (fullName, ' @' );
2063
- const char *eqPtr = uprv_strchr (fullName, ' =' );
2064
- if (atPtr && eqPtr && atPtr < eqPtr) {
2065
- // Key words exist.
2066
- int32_t baseNameLength = static_cast <int32_t >(atPtr - fullName);
2067
- if (baseNameLength == 0 ) { return ; }
2068
-
2069
- if (heap == nullptr ) {
2070
- // There are keywords, so the payload needs to be moved from Nest
2071
- // to Heap so that it can get a baseName.
2072
- const Nest* nest = std::get_if<Nest>(&payload);
2073
- U_ASSERT (nest != nullptr );
2074
- std::unique_ptr<Heap> copy = std::make_unique<Heap>(nest->language ,
2075
- nest->script ,
2076
- nest->region ,
2077
- nest->variantBegin );
2078
- if (!copy) {
2079
- status = U_MEMORY_ALLOCATION_ERROR;
2080
- setToBogus ();
2081
- return ;
2082
- }
2083
- copy->fullName = fullName;
2084
- if (copy->fullName .isEmpty ()) {
2085
- status = U_MEMORY_ALLOCATION_ERROR;
2086
- setToBogus ();
2087
- return ;
2088
- }
2089
- heap = &payload.emplace <std::unique_ptr<Heap>>(std::move (copy));
2090
- if (!*heap) {
2091
- status = U_MEMORY_ALLOCATION_ERROR;
2092
- setToBogus ();
2093
- return ;
2094
- }
2095
- }
2096
-
2097
- // The original computation of variantBegin leaves it equal to the length
2098
- // of fullName if there is no variant. It should instead be
2099
- // the length of the baseName.
2100
- if ((*heap)->variantBegin > baseNameLength) {
2101
- (*heap)->variantBegin = baseNameLength;
2102
- }
2103
-
2104
- (*heap)->baseName = {fullName, static_cast <std::string_view::size_type>(baseNameLength)};
2105
- if ((*heap)->baseName .isEmpty ()) {
2106
- status = U_MEMORY_ALLOCATION_ERROR;
2107
- setToBogus ();
2108
- return ;
2109
- }
2110
- }
2111
- }
2112
-
2113
-
2114
2052
int32_t
2115
2053
Locale::hashCode () const
2116
2054
{
@@ -2753,8 +2691,11 @@ Locale::setKeywordValue(StringPiece keywordName,
2753
2691
return ;
2754
2692
}
2755
2693
2694
+ const char * at = locale_getKeywordsStart (localeID.toStringPiece ());
2695
+ bool hasKeywords = at != nullptr && uprv_strchr (at + 1 , ' =' ) != nullptr ;
2696
+
2756
2697
Nest* nest = std::get_if<Nest>(&payload);
2757
- if (locale_getKeywordsStart (localeID. toStringPiece ()) == nullptr ) {
2698
+ if (!hasKeywords ) {
2758
2699
if (nest == nullptr ) {
2759
2700
// There are no longer any keywords left, so it might now be
2760
2701
// possible to move the payload from Heap to Nest.
@@ -2814,7 +2755,14 @@ Locale::setKeywordValue(StringPiece keywordName,
2814
2755
2815
2756
if ((*heap)->baseName .isEmpty ()) {
2816
2757
// Has added the first keyword, meaning that the fullName is no longer also the baseName.
2817
- initBaseName (status);
2758
+ if (std::string_view::size_type baseNameLength = at - localeID.data (); baseNameLength > 0 ) {
2759
+ (*heap)->baseName = {(*heap)->fullName .data (), baseNameLength};
2760
+ if ((*heap)->baseName .isEmpty ()) {
2761
+ status = U_MEMORY_ALLOCATION_ERROR;
2762
+ setToBogus ();
2763
+ return ;
2764
+ }
2765
+ }
2818
2766
}
2819
2767
}
2820
2768
}
0 commit comments