Skip to content

Commit

Permalink
ICU-22520 Replace char arrays with icu::CharString.
Browse files Browse the repository at this point in the history
  • Loading branch information
roubert committed Dec 29, 2023
1 parent 74abcfe commit 0274059
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 69 deletions.
96 changes: 42 additions & 54 deletions icu4c/source/common/locdspnm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "unicode/udisplaycontext.h"
#include "unicode/brkiter.h"
#include "unicode/ucurr.h"
#include "bytesinkutil.h"
#include "charstr.h"
#include "cmemory.h"
#include "cstring.h"
#include "mutex.h"
Expand All @@ -27,37 +29,6 @@
#include "ureslocs.h"
#include "uresimp.h"

#include <stdarg.h>

/**
* Concatenate a number of null-terminated strings to buffer, leaving a
* null-terminated string. The last argument should be the null pointer.
* Return the length of the string in the buffer, not counting the trailing
* null. Return -1 if there is an error (buffer is null, or buflen < 1).
*/
static int32_t ncat(char *buffer, uint32_t buflen, ...) {
va_list args;
char *str;
char *p = buffer;
const char* e = buffer + buflen - 1;

if (buffer == nullptr || buflen < 1) {
return -1;
}

va_start(args, buflen);
while ((str = va_arg(args, char *)) != 0) {
char c;
while (p != e && (c = *str++) != 0) {
*p++ = c;
}
}
*p = 0;
va_end(args);

return static_cast<int32_t>(p - buffer);
}

U_NAMESPACE_BEGIN

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -575,31 +546,46 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
UBool hasVariant = uprv_strlen(variant) > 0;

if (dialectHandling == ULDN_DIALECT_NAMES) {
char buffer[ULOC_FULLNAME_CAPACITY];
UErrorCode status = U_ZERO_ERROR;
CharString buffer;
do { // loop construct is so we can break early out of search
if (hasScript && hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0);
localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasScript = false;
hasCountry = false;
break;
buffer.append(lang, status)
.append('_', status)
.append(script, status)
.append('_', status)
.append(country, status);
if (U_SUCCESS(status)) {
localeIdName(buffer.data(), resultName, false);
if (!resultName.isBogus()) {
hasScript = false;
hasCountry = false;
break;
}
}
}
if (hasScript) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0);
localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasScript = false;
break;
buffer.append(lang, status)
.append('_', status)
.append(script, status);
if (U_SUCCESS(status)) {
localeIdName(buffer.data(), resultName, false);
if (!resultName.isBogus()) {
hasScript = false;
break;
}
}
}
if (hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0);
localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasCountry = false;
break;
buffer.append(lang, status)
.append('_', status)
.append(country, status);
if (U_SUCCESS(status)) {
localeIdName(buffer.data(), resultName, false);
if (!resultName.isBogus()) {
hasCountry = false;
break;
}
}
}
} while (false);
Expand Down Expand Up @@ -646,21 +632,23 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc,
LocalPointer<StringEnumeration> e(loc.createKeywords(status));
if (e.isValid() && U_SUCCESS(status)) {
UnicodeString temp2;
char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY
const char* key;
while ((key = e->next((int32_t *)0, status)) != nullptr) {
value[0] = 0;
loc.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status);
if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
CharString value;
{
CharStringByteSink sink(&value);
loc.getKeywordValue(key, sink, status);
}
if (U_FAILURE(status)) {
return result;
}
keyDisplayName(key, temp, true);
temp.findAndReplace(formatOpenParen, formatReplaceOpenParen);
temp.findAndReplace(formatCloseParen, formatReplaceCloseParen);
keyValueDisplayName(key, value, temp2, true);
keyValueDisplayName(key, value.data(), temp2, true);
temp2.findAndReplace(formatOpenParen, formatReplaceOpenParen);
temp2.findAndReplace(formatCloseParen, formatReplaceCloseParen);
if (temp2 != UnicodeString(value, -1, US_INV)) {
if (temp2 != UnicodeString(value.data(), -1, US_INV)) {
appendWithSep(resultRemainder, temp2);
} else if (temp != UnicodeString(key, -1, US_INV)) {
UnicodeString temp3;
Expand Down
12 changes: 6 additions & 6 deletions icu4c/source/common/locresdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
/* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/
const char16_t *item=nullptr;
UErrorCode errorCode;
char explicitFallbackName[ULOC_FULLNAME_CAPACITY] = {0};

/*
* open the bundle for the current locale
Expand Down Expand Up @@ -128,15 +127,16 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
*pErrorCode = errorCode;
break;
}

u_UCharsToChars(fallbackLocale, explicitFallbackName, len);


icu::CharString explicitFallbackName;
explicitFallbackName.appendInvariantChars(fallbackLocale, len, errorCode);

/* guard against recursive fallback */
if(uprv_strcmp(explicitFallbackName, locale)==0){
if (explicitFallbackName == locale) {
*pErrorCode = U_INTERNAL_PROGRAM_ERROR;
break;
}
rb.adoptInstead(ures_open(path, explicitFallbackName, &errorCode));
rb.adoptInstead(ures_open(path, explicitFallbackName.data(), &errorCode));
if(U_FAILURE(errorCode)){
*pErrorCode = errorCode;
break;
Expand Down
21 changes: 12 additions & 9 deletions icu4c/source/common/locutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,7 @@ LocaleUtility::canonicalLocaleString(const UnicodeString* id, UnicodeString& res
Locale&
LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
{
enum { BUFLEN = 128 }; // larger than ever needed

if (id.isBogus() || id.length() >= BUFLEN) {
if (id.isBogus()) {
result.setToBogus();
} else {
/*
Expand All @@ -168,24 +166,29 @@ LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
*
* There should be only at most one '@' in a locale ID.
*/
char buffer[BUFLEN];
CharString buffer;
int32_t prev, i;
prev = 0;
for(;;) {
UErrorCode status = U_ZERO_ERROR;
do {
i = id.indexOf((char16_t)0x40, prev);
if(i < 0) {
// no @ between prev and the rest of the string
id.extract(prev, INT32_MAX, buffer + prev, BUFLEN - prev, US_INV);
buffer.appendInvariantChars(id.tempSubString(prev), status);
break; // done
} else {
// normal invariant-character conversion for text between @s
id.extract(prev, i - prev, buffer + prev, BUFLEN - prev, US_INV);
buffer.appendInvariantChars(id.tempSubString(prev, i - prev), status);
// manually "convert" U+0040 at id[i] into '@' at buffer[i]
buffer[i] = '@';
buffer.append('@', status);
prev = i + 1;
}
} while (U_SUCCESS(status));
if (U_FAILURE(status)) {
result.setToBogus();
} else {
result = Locale::createFromName(buffer.data());
}
result = Locale::createFromName(buffer);
}
return result;
}
Expand Down

0 comments on commit 0274059

Please sign in to comment.