ICU-13417 Add the Locale::get(Unicode)?Keywords() functions.
authorFredrik Roubert <fredrik@roubert.name>
Sat, 15 Sep 2018 00:12:06 +0000 (17:12 -0700)
committerShane Carr <shane@unicode.org>
Thu, 27 Sep 2018 21:27:39 +0000 (14:27 -0700)
They are C++ template wrappers around Locale::createKeywords() and
Locale::createUnicodeKeywords() respectively, that write to any
container for which an STL style output iterator can be provided.

The simplest imaginable usage would just look like this:

    std::string keys[16];
    l.getKeywords<std::string>(keys, status);

The unit test has a more elaborate invocation, writing to an std::set<>.

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

index f570391b1bc944d0b2dccdbba8885dcb7eba916b..f1985667b8ac3db363be0d7a0136021b4dce0a1a 100644 (file)
@@ -32,6 +32,8 @@
 #define LOCID_H
 
 #include "unicode/bytestream.h"
+#include "unicode/localpointer.h"
+#include "unicode/strenum.h"
 #include "unicode/stringpiece.h"
 #include "unicode/utypes.h"
 #include "unicode/uobject.h"
@@ -553,6 +555,7 @@ public:
      * @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.
+     * @see getKeywords
      * @stable ICU 2.8
      */
     StringEnumeration * createKeywords(UErrorCode &status) const;
@@ -565,10 +568,41 @@ public:
      * @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.
+     * @see getUnicodeKeywords
      * @draft ICU 63
      */
     StringEnumeration * createUnicodeKeywords(UErrorCode &status) const;
 
+    /**
+     * Gets the set of keywords for this Locale.
+     *
+     * A wrapper to call createKeywords() and write the resulting
+     * keywords as standard strings (or compatible objects) into any kind of
+     * container that can be written to by an STL style output iterator.
+     *
+     * @param iterator  an STL style output iterator to write the keywords to.
+     * @param status    error information if creating set of keywords failed.
+     * @return          a set of strings with all keywords.
+     * @draft ICU 63
+     */
+    template<typename StringClass, typename OutputIterator>
+    inline void getKeywords(OutputIterator iterator, UErrorCode& status) const;
+
+    /**
+     * Gets the set of Unicode keywords for this Locale.
+     *
+     * A wrapper to call createUnicodeKeywords() and write the resulting
+     * keywords as standard strings (or compatible objects) into any kind of
+     * container that can be written to by an STL style output iterator.
+     *
+     * @param iterator  an STL style output iterator to write the keywords to.
+     * @param status    error information if creating set of keywords failed.
+     * @return          a set of strings with all keywords.
+     * @draft ICU 63
+     */
+    template<typename StringClass, typename OutputIterator>
+    inline void getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const;
+
 #endif  // U_HIDE_DRAFT_API
 
     /**
@@ -1062,6 +1096,40 @@ Locale::getName() const
 
 #ifndef U_HIDE_DRAFT_API
 
+template<typename StringClass, typename OutputIterator> inline void
+Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
+{
+    LocalPointer<StringEnumeration> keys(createKeywords(status));
+    if (U_FAILURE(status)) {
+        return;
+    }
+    for (;;) {
+        int32_t resultLength;
+        const char* buffer = keys->next(&resultLength, status);
+        if (U_FAILURE(status) || buffer == nullptr) {
+            return;
+        }
+        *iterator++ = StringClass(buffer, resultLength);
+    }
+}
+
+template<typename StringClass, typename OutputIterator> inline void
+Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
+{
+    LocalPointer<StringEnumeration> keys(createUnicodeKeywords(status));
+    if (U_FAILURE(status)) {
+        return;
+    }
+    for (;;) {
+        int32_t resultLength;
+        const char* buffer = keys->next(&resultLength, status);
+        if (U_FAILURE(status) || buffer == nullptr) {
+            return;
+        }
+        *iterator++ = StringClass(buffer, resultLength);
+    }
+}
+
 template<typename StringClass> inline StringClass
 Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const
 {
index c86db1bed33f5657cdd2f0a9a08cbe6a75beec6c..0ca3e40e48c1e8eb56ab0697267ba2e0e08c9370 100644 (file)
@@ -6,6 +6,9 @@
  * others. All Rights Reserved.
  ********************************************************************/
 
+#include <iterator>
+#include <set>
+
 #include "loctest.h"
 #include "unicode/localpointer.h"
 #include "unicode/decimfmt.h"
@@ -226,6 +229,8 @@ void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, c
     TESTCASE_AUTO(TestKeywordVariants);
     TESTCASE_AUTO(TestCreateUnicodeKeywords);
     TESTCASE_AUTO(TestKeywordVariantParsing);
+    TESTCASE_AUTO(TestCreateKeywordSet);
+    TESTCASE_AUTO(TestCreateUnicodeKeywordSet);
     TESTCASE_AUTO(TestGetKeywordValueStdString);
     TESTCASE_AUTO(TestGetUnicodeKeywordValueStdString);
     TESTCASE_AUTO(TestSetKeywordValue);
@@ -1824,6 +1829,44 @@ LocaleTest::TestKeywordVariantParsing(void) {
     }
 }
 
+void
+LocaleTest::TestCreateKeywordSet(void) {
+    IcuTestErrorCode status(*this, "TestCreateKeywordSet()");
+
+    static const Locale l("de@calendar=buddhist;collation=phonebook");
+
+    std::set<std::string> result;
+    l.getKeywords<std::string>(
+            std::insert_iterator<decltype(result)>(result, result.begin()),
+            status);
+    status.errIfFailureAndReset("\"%s\"", l.getName());
+
+    assertEquals("set::size()", 2, result.size());
+    assertTrue("set::find(\"calendar\")",
+               result.find("calendar") != result.end());
+    assertTrue("set::find(\"collation\")",
+               result.find("collation") != result.end());
+}
+
+void
+LocaleTest::TestCreateUnicodeKeywordSet(void) {
+    IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSet()");
+
+    static const Locale l("de@calendar=buddhist;collation=phonebook");
+
+    std::set<std::string> result;
+    l.getUnicodeKeywords<std::string>(
+            std::insert_iterator<decltype(result)>(result, result.begin()),
+            status);
+    status.errIfFailureAndReset("\"%s\"", l.getName());
+
+    assertEquals("set::size()", 2, result.size());
+    assertTrue("set::find(\"ca\")",
+               result.find("ca") != result.end());
+    assertTrue("set::find(\"co\")",
+               result.find("co") != result.end());
+}
+
 void
 LocaleTest::TestGetKeywordValueStdString(void) {
     IcuTestErrorCode status(*this, "TestGetKeywordValueStdString()");
index e93b17df84a0cab9574e1e15bf25d86530ff5b65..8c8d7da2eb4ce923f1ca7c57c3e92b617d0b189e 100644 (file)
@@ -78,6 +78,8 @@ public:
 
    /* Test getting keyword values */
    void TestKeywordVariantParsing(void);
+   void TestCreateKeywordSet(void);
+   void TestCreateUnicodeKeywordSet(void);
    void TestGetKeywordValueStdString(void);
    void TestGetUnicodeKeywordValueStdString(void);