@@ -1957,6 +1957,7 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
19571957 } else {
19581958 fieldLen[fieldIdx - 1 ] = length - static_cast <int32_t >(field[fieldIdx - 1 ] - fullName);
19591959 }
1960+ bool hasKeywords = at != nullptr && uprv_strchr (at + 1 , ' =' ) != nullptr ;
19601961
19611962 if (fieldLen[0 ] >= ULOC_LANG_CAPACITY)
19621963 {
@@ -1987,9 +1988,14 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
19871988 if (fieldLen[variantField] > 0 ) {
19881989 /* We have a variant */
19891990 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);
19901996 }
19911997
1992- if (Nest::fits (length, language, script, region)) {
1998+ if (!hasKeywords && Nest::fits (length, language, script, region)) {
19931999 U_ASSERT (fullName == nest.baseName );
19942000 U_ASSERT (fullNameBuffer.isEmpty ());
19952001 nest.init (language, script, region, variantBegin);
@@ -2008,11 +2014,14 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
20082014 }
20092015 U_ASSERT (!fullNameBuffer.isEmpty ());
20102016 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+ }
20162025 }
20172026
20182027 if (canonicalize) {
@@ -2040,77 +2049,6 @@ Locale& Locale::init(StringPiece localeID, UBool canonicalize)
20402049 return *this ;
20412050}
20422051
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-
21142052int32_t
21152053Locale::hashCode () const
21162054{
@@ -2753,8 +2691,11 @@ Locale::setKeywordValue(StringPiece keywordName,
27532691 return ;
27542692 }
27552693
2694+ const char * at = locale_getKeywordsStart (localeID.toStringPiece ());
2695+ bool hasKeywords = at != nullptr && uprv_strchr (at + 1 , ' =' ) != nullptr ;
2696+
27562697 Nest* nest = std::get_if<Nest>(&payload);
2757- if (locale_getKeywordsStart (localeID. toStringPiece ()) == nullptr ) {
2698+ if (!hasKeywords ) {
27582699 if (nest == nullptr ) {
27592700 // There are no longer any keywords left, so it might now be
27602701 // possible to move the payload from Heap to Nest.
@@ -2814,7 +2755,14 @@ Locale::setKeywordValue(StringPiece keywordName,
28142755
28152756 if ((*heap)->baseName .isEmpty ()) {
28162757 // 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+ }
28182766 }
28192767 }
28202768}
0 commit comments