diff --git a/icu4c/source/common/localebuilder.cpp b/icu4c/source/common/localebuilder.cpp index fe931fcf759..28ddf514b48 100644 --- a/icu4c/source/common/localebuilder.cpp +++ b/icu4c/source/common/localebuilder.cpp @@ -433,4 +433,13 @@ Locale LocaleBuilder::build(UErrorCode& errorCode) return product; } +UBool LocaleBuilder::copyErrorTo(UErrorCode &outErrorCode) { + if (U_FAILURE(outErrorCode)) { + // Do not overwrite the older error code + return TRUE; + } + outErrorCode = status_; + return U_FAILURE(outErrorCode); +} + U_NAMESPACE_END diff --git a/icu4c/source/common/unicode/localebuilder.h b/icu4c/source/common/unicode/localebuilder.h index cc5eec9cafb..78f7efcfbb8 100644 --- a/icu4c/source/common/unicode/localebuilder.h +++ b/icu4c/source/common/unicode/localebuilder.h @@ -279,6 +279,17 @@ public: */ Locale build(UErrorCode& status); + /** + * Sets the UErrorCode if an error occurred while recording sets. + * Preserves older error codes in the outErrorCode. + * @param outErrorCode Set to an error code that occurred while setting subtags. + * Unchanged if there is no such error or if outErrorCode + * already contained an error. + * @return TRUE if U_FAILURE(outErrorCode) + * @draft ICU 65 + */ + UBool copyErrorTo(UErrorCode &outErrorCode); + private: UErrorCode status_; char language_[9]; diff --git a/icu4c/source/test/intltest/localebuildertest.cpp b/icu4c/source/test/intltest/localebuildertest.cpp index cf3bd748870..24beb6aebb8 100644 --- a/icu4c/source/test/intltest/localebuildertest.cpp +++ b/icu4c/source/test/intltest/localebuildertest.cpp @@ -55,10 +55,21 @@ void LocaleBuilderTest::runIndexedTest( int32_t index, UBool exec, const char* & void LocaleBuilderTest::Verify(LocaleBuilder& bld, const char* expected, const char* msg) { UErrorCode status = U_ZERO_ERROR; + UErrorCode copyStatus = U_ZERO_ERROR; + UErrorCode errorStatus = U_ILLEGAL_ARGUMENT_ERROR; + if (bld.copyErrorTo(copyStatus)) { + errln(msg, u_errorName(copyStatus)); + } + if (!bld.copyErrorTo(errorStatus) || errorStatus != U_ILLEGAL_ARGUMENT_ERROR) { + errln("Should always get the previous error and return FALSE"); + } Locale loc = bld.build(status); if (U_FAILURE(status)) { errln(msg, u_errorName(status)); } + if (status != copyStatus) { + errln(msg, u_errorName(status)); + } std::string tag = loc.toLanguageTag(status); if (U_FAILURE(status)) { errln("loc.toLanguageTag() got Error: %s\n", @@ -190,39 +201,67 @@ void LocaleBuilderTest::TestLocaleBuilder() { status = U_ZERO_ERROR; bld.clear(); while (true) { + status = U_ZERO_ERROR; + UErrorCode copyStatus = U_ZERO_ERROR; method = testCase[i++]; if (strcmp("L", method) == 0) { - bld.setLanguage(testCase[i++]).build(status); + bld.setLanguage(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("S", method) == 0) { - bld.setScript(testCase[i++]).build(status); + bld.setScript(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("R", method) == 0) { - bld.setRegion(testCase[i++]).build(status); + bld.setRegion(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("V", method) == 0) { - bld.setVariant(testCase[i++]).build(status); + bld.setVariant(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("K", method) == 0) { const char* key = testCase[i++]; const char* type = testCase[i++]; - bld.setUnicodeLocaleKeyword(key, type).build(status); + bld.setUnicodeLocaleKeyword(key, type); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("A", method) == 0) { - bld.addUnicodeLocaleAttribute(testCase[i++]).build(status); + bld.addUnicodeLocaleAttribute(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("E", method) == 0) { const char* key = testCase[i++]; const char* value = testCase[i++]; - bld.setExtension(key[0], value).build(status); + bld.setExtension(key[0], value); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("P", method) == 0) { - bld.setExtension('x', testCase[i++]).build(status); + bld.setExtension('x', testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("U", method) == 0) { - bld.setLocale(Locale(testCase[i++])).build(status); + bld.setLocale(Locale(testCase[i++])); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("B", method) == 0) { - bld.setLanguageTag(testCase[i++]).build(status); + bld.setLanguageTag(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } // clear / remove else if (strcmp("C", method) == 0) { - bld.clear().build(status); + bld.clear(); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("N", method) == 0) { - bld.clearExtensions().build(status); + bld.clearExtensions(); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("D", method) == 0) { - bld.removeUnicodeLocaleAttribute(testCase[i++]).build(status); + bld.removeUnicodeLocaleAttribute(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } // result else if (strcmp("X", method) == 0) { @@ -232,6 +271,9 @@ void LocaleBuilderTest::TestLocaleBuilder() { } else if (strcmp("T", method) == 0) { status = U_ZERO_ERROR; Locale loc = bld.build(status); + if (status != copyStatus) { + errln("copyErrorTo not matching"); + } if (U_FAILURE(status) || strcmp(loc.getName(), testCase[i + 1]) != 0) { errln("FAIL: Wrong locale ID - %s %s %s", loc.getName(), @@ -248,6 +290,9 @@ void LocaleBuilderTest::TestLocaleBuilder() { errln("Unknown test case method: There is an error in the test case data."); break; } + if (status != copyStatus) { + errln("copyErrorTo not matching"); + } if (U_FAILURE(status)) { if (strcmp("X", testCase[i]) == 0) { // This failure is expected