From 7eb56fee1ec2ce125c92f3a38003f743cb738992 Mon Sep 17 00:00:00 2001 From: Fredrik Roubert Date: Wed, 27 Dec 2023 19:54:32 +0900 Subject: [PATCH] ICU-22520 Remove now superfluous intermediate buffers. --- icu4c/source/common/loclikely.cpp | 163 ++++++------------------------ 1 file changed, 31 insertions(+), 132 deletions(-) diff --git a/icu4c/source/common/loclikely.cpp b/icu4c/source/common/loclikely.cpp index c63a38d4265c..bbcc0017380c 100644 --- a/icu4c/source/common/loclikely.cpp +++ b/icu4c/source/common/loclikely.cpp @@ -19,6 +19,8 @@ * that then do not depend on resource bundle code and likely-subtags data. */ +#include + #include "unicode/bytestream.h" #include "unicode/utypes.h" #include "unicode/locid.h" @@ -35,37 +37,6 @@ #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; -} - /** * 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 @@ -114,51 +85,24 @@ createTagStringWithAlternates( goto error; } 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); + sink.Append(lang, langLength); } if (scriptLength > 0) { - appendTag( - script, - scriptLength, - tagBuffer, - &tagLength, - /*withSeparator=*/true); + sink.Append("_", 1); + sink.Append(script, scriptLength); } if (regionLength > 0) { - appendTag( - region, - regionLength, - tagBuffer, - &tagLength, - /*withSeparator=*/true); + sink.Append("_", 1); + sink.Append(region, regionLength); 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); @@ -192,58 +136,33 @@ createTagStringWithAlternates( /** * 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. + * results into the corresponding output parameters. * * 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, + icu::CharString& lang, + icu::CharString& script, + icu::CharString& region, 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) { + + if (U_FAILURE(*err) || localeID == nullptr) { goto error; } - subtagLength = ulocimp_getLanguage(position, &position, *err).extract(lang, *langLength, *err); + lang = ulocimp_getLanguage(position, &position, *err); /* * Note that we explicit consider U_STRING_NOT_TERMINATED_WARNING @@ -254,8 +173,6 @@ parseTagString( goto error; } - *langLength = subtagLength; - /* * If no language was present, use the empty string instead. * Otherwise, move past any separator. @@ -264,15 +181,13 @@ parseTagString( ++position; } - subtagLength = ulocimp_getScript(position, &position, *err).extract(script, *scriptLength, *err); + script = ulocimp_getScript(position, &position, *err); if(U_FAILURE(*err)) { goto error; } - *scriptLength = subtagLength; - - if (*scriptLength > 0) { + if (!script.isEmpty()) { /* * Move past any separator. */ @@ -281,15 +196,13 @@ parseTagString( } } - subtagLength = ulocimp_getCountry(position, &position, *err).extract(region, *regionLength, *err); + region = ulocimp_getCountry(position, &position, *err); if(U_FAILURE(*err)) { goto error; } - *regionLength = subtagLength; - - if (*regionLength <= 0 && *position != 0 && *position != '@') { + if (region.isEmpty() && *position != 0 && *position != '@') { /* back up over consumed trailing separator */ --position; } @@ -334,12 +247,9 @@ 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); + icu::CharString lang; + icu::CharString script; + icu::CharString region; const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; @@ -354,11 +264,8 @@ _uloc_addLikelySubtags(const char* localeID, trailingIndex = parseTagString( localeID, lang, - &langLength, script, - &scriptLength, region, - ®ionLength, err); if(U_FAILURE(*err)) { /* Overflow indicates an illegal argument error */ @@ -368,12 +275,10 @@ _uloc_addLikelySubtags(const char* localeID, goto error; } - if (langLength > 3) { - if (langLength == 4 && scriptLength == 0) { - langLength = 0; - scriptLength = 4; - uprv_memcpy(script, lang, 4); - lang[0] = '\0'; + if (lang.length() > 3) { + if (lang.length() == 4 && script.isEmpty()) { + script = std::move(lang); + lang.clear(); } else { goto error; } @@ -444,12 +349,9 @@ _uloc_minimizeSubtags(const char* localeID, 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); + icu::CharString lang; + icu::CharString script; + icu::CharString region; const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; @@ -465,11 +367,8 @@ _uloc_minimizeSubtags(const char* localeID, parseTagString( localeID, lang, - &langLength, script, - &scriptLength, region, - ®ionLength, err); if(U_FAILURE(*err)) { @@ -496,9 +395,9 @@ _uloc_minimizeSubtags(const char* localeID, goto error; } icu::LSR lsr = likelySubtags->minimizeSubtags( - {lang, langLength}, - {script, scriptLength}, - {region, regionLength}, + lang.toStringPiece(), + script.toStringPiece(), + region.toStringPiece(), favorScript, *err); if(U_FAILURE(*err)) {