ICU-22520 Remove now superfluous intermediate buffers.

This commit is contained in:
Fredrik Roubert 2023-12-27 19:54:32 +09:00 committed by Fredrik Roubert
parent 5fa7d4c7ff
commit 7eb56fee1e

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"
@ -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 @@ 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.
* 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,
&regionLength,
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,
&regionLength,
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)) {