]> granicus.if.org Git - icu/commitdiff
ICU-13417 Add the Locale::createUnicodeKeywords() function.
authorFredrik Roubert <roubert@google.com>
Thu, 13 Sep 2018 23:08:29 +0000 (16:08 -0700)
committerShane Carr <shane@unicode.org>
Thu, 27 Sep 2018 21:27:39 +0000 (14:27 -0700)
This is a wrapper of Locale::createKeywords() that under the hood calls
uloc_toUnicodeLocaleKey() for each key before returning it, so that the
caller won't have to do this.

icu4c/source/common/locid.cpp
icu4c/source/common/unicode/locid.h
icu4c/source/test/intltest/loctest.cpp
icu4c/source/test/intltest/loctest.h

index fe52afc9f3120fb385645048d56fcaa8455f1de5..784193f251174330d9a1deca9a8f6e33b73b6e2a 100644 (file)
@@ -1174,6 +1174,29 @@ KeywordEnumeration::~KeywordEnumeration() {
     uprv_free(keywords);
 }
 
+// A wrapper around KeywordEnumeration that calls uloc_toUnicodeLocaleKey() in
+// the next() method for each keyword before returning it.
+class UnicodeKeywordEnumeration : public KeywordEnumeration {
+public:
+    using KeywordEnumeration::KeywordEnumeration;
+    virtual ~UnicodeKeywordEnumeration() = default;
+
+    virtual const char* next(int32_t* resultLength, UErrorCode& status) {
+        const char* legacy_key = KeywordEnumeration::next(nullptr, status);
+        if (U_SUCCESS(status) && legacy_key != nullptr) {
+            const char* key = uloc_toUnicodeLocaleKey(legacy_key);
+            if (key == nullptr) {
+                status = U_ILLEGAL_ARGUMENT_ERROR;
+            } else {
+                if (resultLength != nullptr) *resultLength = uprv_strlen(key);
+                return key;
+            }
+        }
+        if (resultLength != nullptr) *resultLength = 0;
+        return nullptr;
+    }
+};
+
 StringEnumeration *
 Locale::createKeywords(UErrorCode &status) const
 {
@@ -1196,6 +1219,28 @@ Locale::createKeywords(UErrorCode &status) const
     return result;
 }
 
+StringEnumeration *
+Locale::createUnicodeKeywords(UErrorCode &status) const
+{
+    char keywords[256];
+    int32_t keywordCapacity = 256;
+    StringEnumeration *result = NULL;
+
+    const char* variantStart = uprv_strchr(fullName, '@');
+    const char* assignment = uprv_strchr(fullName, '=');
+    if(variantStart) {
+        if(assignment > variantStart) {
+            int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status);
+            if(keyLen) {
+                result = new UnicodeKeywordEnumeration(keywords, keyLen, 0, status);
+            }
+        } else {
+            status = U_INVALID_FORMAT_ERROR;
+        }
+    }
+    return result;
+}
+
 int32_t
 Locale::getKeywordValue(const char* keywordName, char *buffer, int32_t bufLen, UErrorCode &status) const
 {
index ef8df739a001b47d9969fcbbaf91325d49c76f3d..962e6ddb269992e9ec26f84e40bac3b99387ad79 100644 (file)
@@ -494,6 +494,20 @@ public:
      */
     StringEnumeration * createKeywords(UErrorCode &status) const;
 
+#ifndef U_HIDE_DRAFT_API
+
+    /**
+     * Gets the list of Unicode keywords for the specified locale.
+     *
+     * @param status the status code
+     * @return pointer to StringEnumeration class, or NULL if there are no keywords.
+     * Client must dispose of it by calling delete.
+     * @draft ICU 63
+     */
+    StringEnumeration * createUnicodeKeywords(UErrorCode &status) const;
+
+#endif  // U_HIDE_DRAFT_API
+
     /**
      * Gets the value for a keyword.
      *
index cd75670cff6c9eaacd3fec4734d8546ae26126e0..33174cba05ce003e7a87c399b4fab6361336e031 100644 (file)
@@ -7,6 +7,7 @@
  ********************************************************************/
 
 #include "loctest.h"
+#include "unicode/localpointer.h"
 #include "unicode/decimfmt.h"
 #include "unicode/ucurr.h"
 #include "unicode/smpdtfmt.h"
@@ -221,6 +222,7 @@ void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, c
     TESTCASE_AUTO(TestSetIsBogus);
     TESTCASE_AUTO(TestParallelAPIValues);
     TESTCASE_AUTO(TestKeywordVariants);
+    TESTCASE_AUTO(TestCreateUnicodeKeywords);
     TESTCASE_AUTO(TestKeywordVariantParsing);
     TESTCASE_AUTO(TestSetKeywordValue);
     TESTCASE_AUTO(TestGetBaseName);
@@ -1708,6 +1710,55 @@ LocaleTest::TestKeywordVariants(void) {
 
 }
 
+
+void
+LocaleTest::TestCreateUnicodeKeywords(void) {
+    IcuTestErrorCode status(*this, "TestCreateUnicodeKeywords()");
+
+    static const Locale l("de@calendar=buddhist;collation=phonebook");
+
+    LocalPointer<StringEnumeration> keys(l.createUnicodeKeywords(status));
+    status.errIfFailureAndReset("\"%s\"", l.getName());
+
+    const char* key;
+    int32_t resultLength;
+
+    key = keys->next(&resultLength, status);
+    status.errIfFailureAndReset("key #1");
+    assertEquals("resultLength", 2, resultLength);
+    assertTrue("key != nullptr", key != nullptr);
+    assertEquals("calendar", "ca", key);
+
+    key = keys->next(&resultLength, status);
+    status.errIfFailureAndReset("key #2");
+    assertEquals("resultLength", 2, resultLength);
+    assertTrue("key != nullptr", key != nullptr);
+    assertEquals("collation", "co", key);
+
+    key = keys->next(&resultLength, status);
+    status.errIfFailureAndReset("end of keys");
+    assertEquals("resultLength", 0, resultLength);
+    assertTrue("key == nullptr", key == nullptr);
+
+    const UnicodeString* skey;
+    keys->reset(status);  // KeywordEnumeration::reset() never touches status.
+
+    skey = keys->snext(status);
+    status.errIfFailureAndReset("skey #1");
+    assertTrue("skey != nullptr", skey != nullptr);
+    assertEquals("calendar", "ca", *skey);
+
+    skey = keys->snext(status);
+    status.errIfFailureAndReset("skey #2");
+    assertTrue("skey != nullptr", skey != nullptr);
+    assertEquals("collation", "co", *skey);
+
+    skey = keys->snext(status);
+    status.errIfFailureAndReset("end of keys");
+    assertTrue("skey == nullptr", skey == nullptr);
+}
+
+
 void
 LocaleTest::TestKeywordVariantParsing(void) {
     static const struct {
index 529df214df8ae1f2ddb0dbeafcfee53b1b38ed90..7bb52f47a9f8e5adb9b1b13fa8e5866267badb47 100644 (file)
@@ -72,8 +72,9 @@ public:
     
     void TestVariantParsing(void);
 
-   /* Test getting keyword enumeratin */
+   /* Test getting keyword enumeration */
    void TestKeywordVariants(void);
+   void TestCreateUnicodeKeywords(void);
 
    /* Test getting keyword values */
    void TestKeywordVariantParsing(void);