ICU-22365 Add adoptULocale and buildULocale to ULocaleBuilder

Add two methods related to ULocale to ULocaleBuilder API

void ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale);
ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err);

ICU TC approved this in 2023-08-31
This commit is contained in:
Frank Tang 2023-08-17 15:01:03 -07:00 committed by Frank Yung-Fong Tang
parent fab5faa3aa
commit c294c3272c
3 changed files with 119 additions and 0 deletions

View file

@ -48,6 +48,13 @@ void ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t leng
INTERNAL(builder)->setLocale(l);
}
void
ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale) {
if (builder == nullptr) return;
INTERNAL(builder)->setLocale(*(reinterpret_cast<const icu::Locale*>(locale)));
ulocale_close(locale);
}
#define STRING_PIECE(s, l) ((l)<0 ? StringPiece(s) : StringPiece((s), (l)))
#define IMPL_ULOCBLD_SETTER(N) \
@ -87,6 +94,22 @@ void ulocbld_clearExtensions(ULocaleBuilder* builder) {
INTERNAL(builder)->clearExtensions();
}
ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err) {
if (builder == nullptr) {
*err = U_ILLEGAL_ARGUMENT_ERROR;
return nullptr;
}
icu::Locale l = INTERNAL(builder)->build(*err);
if (U_FAILURE(*err)) return nullptr;
icu::Locale* r = l.clone();
if (r == nullptr) {
*err = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
return reinterpret_cast<ULocale*>(r);
}
int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder,
char* buffer, int32_t bufferCapacity, UErrorCode* err) {
if (builder == nullptr) {

View file

@ -4,6 +4,7 @@
#define __ULOCBUILDER_H__
#include "unicode/localpointer.h"
#include "unicode/ulocale.h"
#include "unicode/utypes.h"
/**
@ -101,6 +102,22 @@ ulocbld_close(ULocaleBuilder* builder);
U_CAPI void U_EXPORT2
ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t length);
/**
* Resets the <code>ULocaleBuilder</code> to match the provided
* <code>ULocale</code>. Existing state is discarded.
*
* <p>The locale must be not bogus.
* <p>This method clears the internal UErrorCode.
*
* @param builder the builder.
* @param locale the locale, a ULocale* pointer. The builder adopts the locale
* after the call and the client must not delete it.
*
* @draft ICU 74
*/
U_CAPI void U_EXPORT2
ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale);
/**
* Resets the ULocaleBuilder to match the provided IETF BCP 47 language tag.
* Discards the existing state.
@ -347,6 +364,24 @@ U_CAPI int32_t U_EXPORT2
ulocbld_buildLocaleID(ULocaleBuilder* builder, char* locale,
int32_t localeCapacity, UErrorCode* err);
/**
* Build the ULocale object from the fields set on this builder.
* If any set methods or during the ulocbld_buildULocale() call require memory
* allocation but fail U_MEMORY_ALLOCATION_ERROR will be set to status.
* If any of the fields set by the setters are not well-formed, the status
* will be set to U_ILLEGAL_ARGUMENT_ERROR. The state of the builder will
* not change after the ulocbld_buildULocale() call and the caller is
* free to keep using the same builder to build more locales.
*
* @param builder the builder.
* @param err the error code.
* @return the locale, a ULocale* pointer. The created ULocale must be
* destroyed by calling {@link ulocale_close}.
* @draft ICU 74
*/
U_CAPI ULocale* U_EXPORT2
ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err);
/**
* Build the IETF BCP 47 language tag string from the fields set on this builder.
* If any set methods or during the ulocbld_buildLanguageTag() call require memory

View file

@ -5,6 +5,11 @@
#include "cstring.h"
#include "unicode/uloc.h"
#include "unicode/ulocbuilder.h"
#include "unicode/ulocale.h"
#define WHERE __FILE__ ":" XLINE(__LINE__) " "
#define XLINE(s) LINE(s)
#define LINE(s) #s
#ifndef UPRV_LENGTHOF
#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
@ -1674,6 +1679,61 @@ static void TestSetLocale() {
ulocbld_close(bld2);
}
static void TestBuildULocale() {
ULocaleBuilder* bld1 = ulocbld_open();
UErrorCode status = U_ZERO_ERROR;
ulocbld_setLanguage(bld1, "fr", -1);
ULocale* fr = ulocbld_buildULocale(bld1, &status);
if (assertSuccess(WHERE "ulocbld_buildULocale()", &status)) {
assertEquals(WHERE "ulocale_getLanguage()", "fr", ulocale_getLanguage(fr));
}
ulocbld_setLanguage(bld1, "ar", -1);
ulocbld_setScript(bld1, "Arab", -1);
ulocbld_setRegion(bld1, "EG", -1);
ulocbld_setVariant(bld1, "3456-abcde", -1);
ulocbld_setUnicodeLocaleKeyword(bld1, "nu", -1, "thai", -1);
ulocbld_setUnicodeLocaleKeyword(bld1, "co", -1, "stroke", -1);
ulocbld_setUnicodeLocaleKeyword(bld1, "ca", -1, "chinese", -1);
ULocale* l = ulocbld_buildULocale(bld1, &status);
if (assertSuccess(WHERE "ulocbld_buildULocale()", &status)) {
assertEquals(WHERE "ulocale_getLanguage()", "ar", ulocale_getLanguage(l));
assertEquals(WHERE "ulocale_getScript()", "Arab", ulocale_getScript(l));
assertEquals(WHERE "ulocale_getRegion()", "EG", ulocale_getRegion(l));
assertEquals(WHERE "ulocale_getVariant()", "3456_ABCDE", ulocale_getVariant(l));
char buf[ULOC_FULLNAME_CAPACITY];
assertIntEquals(WHERE "ulocale_getUnicodeKeywordValue(\"nu\")", 4,
ulocale_getUnicodeKeywordValue(l, "nu", -1, buf, ULOC_FULLNAME_CAPACITY, &status));
if (assertSuccess(WHERE "ulocale_getUnicodeKeywordValue(\"nu\")", &status)) {
assertEquals(WHERE "ulocale_getUnicodeKeywordValue(\"nu\")", "thai", buf);
}
status = U_ZERO_ERROR;
assertIntEquals(WHERE "ulocale_getUnicodeKeywordValue(\"co\")", 6,
ulocale_getUnicodeKeywordValue(l, "co", -1, buf, ULOC_FULLNAME_CAPACITY, &status));
if (assertSuccess(WHERE "ulocale_getUnicodeKeywordValue(\"co\")", &status)) {
assertEquals(WHERE "ulocale_getUnicodeKeywordValue(\"co\")", "stroke", buf);
}
status = U_ZERO_ERROR;
assertIntEquals(WHERE "ulocale_getUnicodeKeywordValue(\"ca\")", 7,
ulocale_getUnicodeKeywordValue(l, "ca", -1, buf, ULOC_FULLNAME_CAPACITY, &status));
if (assertSuccess(WHERE "ulocale_getUnicodeKeywordValue(\"ca\")", &status)) {
assertEquals(WHERE "ulocale_getUnicodeKeywordValue(\"ca\")", "chinese", buf);
}
ulocale_close(l);
}
ulocbld_adoptULocale(bld1, fr);
char buf[ULOC_FULLNAME_CAPACITY];
ulocbld_buildLocaleID(bld1, buf, ULOC_FULLNAME_CAPACITY, &status);
if (assertSuccess(WHERE "ulocbld_buildULocale()", &status)) {
assertEquals(WHERE "ulocbld_buildULocale()", "fr", buf);
}
ulocbld_close(bld1);
}
static void TestPosixCases() {
UErrorCode status = U_ZERO_ERROR;
@ -1731,5 +1791,6 @@ void addLocaleBuilderTest(TestNode** root)
TESTCASE(TestSetExtensionValidateOthersWellFormed);
TESTCASE(TestSetExtensionValidateOthersIllFormed);
TESTCASE(TestSetLocale);
TESTCASE(TestBuildULocale);
TESTCASE(TestPosixCases);
}