]> granicus.if.org Git - icu/commitdiff
ICU-12772 Add uprules_getKeywords wrapper and test
authorPeter Edberg <pedberg@unicode.org>
Thu, 23 Mar 2017 05:16:24 +0000 (05:16 +0000)
committerPeter Edberg <pedberg@unicode.org>
Thu, 23 Mar 2017 05:16:24 +0000 (05:16 +0000)
X-SVN-Rev: 39916

icu4c/source/i18n/unicode/upluralrules.h
icu4c/source/i18n/upluralrules.cpp
icu4c/source/test/cintltst/cpluralrulestest.c

index 7f2d000c95ab415ba469ca054bd2e90a3b08e5ca..25a0dcd9d6d23ee545983d9aeec500c3d779a56c 100644 (file)
@@ -15,6 +15,7 @@
 #if !UCONFIG_NO_FORMATTING
 
 #include "unicode/localpointer.h"
+#include "unicode/uenum.h"
 #ifndef U_HIDE_INTERNAL_API
 #include "unicode/unum.h"
 #endif  /* U_HIDE_INTERNAL_API */
@@ -174,6 +175,22 @@ uplrules_selectWithFormat(const UPluralRules *uplrules,
 
 #endif  /* U_HIDE_INTERNAL_API */
 
+#ifndef U_HIDE_DRAFT_API
+/**
+ * Creates a string enumeration of all plural rule keywords used in this
+ * UPluralRules object. The rule "other" is always present by default.
+ * @param uplrules The UPluralRules object specifying the rules for
+ *        a given locale.
+ * @param status A pointer to a UErrorCode to receive any errors.
+ * @return a string enumeration over plural rule keywords, or NULL
+ * upon error. The caller is responsible for closing the result.
+ * @draft ICU 59
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+uplrules_getKeywords(const UPluralRules *uplrules,
+                     UErrorCode *status);
+#endif  /* U_HIDE_DRAFT_API */
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
 #endif
index 4eab7b23082e7d3b2cdc960fa459e4a4cc125f34..24e74e3ee223f532a83a91b7a55ad2ccc2a8caf0 100644 (file)
@@ -77,4 +77,27 @@ uplrules_selectWithFormat(const UPluralRules *uplrules,
     return result.extract(keyword, capacity, *status);
 }
 
+U_CAPI UEnumeration* U_EXPORT2
+uplrules_getKeywords(const UPluralRules *uplrules,
+                     UErrorCode *status)
+{
+    if (U_FAILURE(*status)) {
+        return NULL;
+    }
+    const PluralRules* plrules = reinterpret_cast<const PluralRules*>(uplrules);
+    if (plrules == NULL) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
+    }
+    StringEnumeration *senum = plrules->getKeywords(*status);
+    if (U_FAILURE(*status)) {
+        return NULL;
+    }
+    if (senum == NULL) {
+        *status = U_MEMORY_ALLOCATION_ERROR;
+        return NULL;
+    }
+    return uenum_openFromStringEnumeration(senum, status);
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
index 1a784a9f5a868d9e89112bac8ab2bfbce0450e39..24b65433f69a7cb9251304d476a1c3dbd9ed70d2 100644 (file)
 
 #include "unicode/upluralrules.h"
 #include "unicode/ustring.h"
+#include "unicode/uenum.h"
 #include "cintltst.h"
 #include "cmemory.h"
+#include "cstring.h"
 
 static void TestPluralRules(void);
 static void TestOrdinalRules(void);
+static void TestGetKeywords(void);
 
 void addPluralRulesTest(TestNode** root);
 
@@ -26,6 +29,7 @@ void addPluralRulesTest(TestNode** root)
 {
     TESTCASE(TestPluralRules);
     TESTCASE(TestOrdinalRules);
+    TESTCASE(TestGetKeywords);
 }
 
 typedef struct {
@@ -139,4 +143,113 @@ static void TestOrdinalRules() {
     uplrules_close(upr);
 }
 
+/* items for TestGetKeywords */
+
+/* all possible plural keywords, in alphabetical order */
+static const char* knownKeywords[] = {
+    "few",
+    "many",
+    "one",
+    "other",
+    "two",
+    "zero"
+};
+enum {
+    kNumKeywords = UPRV_LENGTHOF(knownKeywords)
+};
+
+/* Return the index of keyword in knownKeywords[], or -1 if not found */
+static int32_t getKeywordIndex(const char* keyword) {
+    int32_t i, compare;
+    for (i = 0; i < kNumKeywords && (compare = uprv_strcmp(keyword,knownKeywords[i])) >= 0; i++) {
+        if (compare == 0) {
+               return i;
+        }
+    }
+    return -1;
+}
+
+typedef struct {
+    const char* locale;
+    const char* keywords[kNumKeywords + 1];
+} KeywordsForLang;
+
+static const KeywordsForLang getKeywordsItems[] = {
+    { "zh", { "other" } },
+    { "en", { "one", "other" } },
+    { "fr", { "one", "other" } },
+    { "lv", { "zero", "one", "other" } },
+    { "hr", { "one", "few", "other" } },
+    { "sl", { "one", "two", "few", "other" } },
+    { "he", { "one", "two", "many", "other" } },
+    { "cs", { "one", "few", "many", "other" } },
+    { "ar", { "zero", "one", "two", "few", "many" , "other" } },
+    { NULL, { NULL } }
+};
+
+static void TestGetKeywords() {
+    /*
+     * We don't know the order in which the enumeration will return keywords,
+     * so we have an array with known keywords in a fixed order and then
+     * parallel arrays of flags for expected and actual results that indicate
+     * which keywords are expected to be or actually are found.
+     */
+    const KeywordsForLang* itemPtr = getKeywordsItems;
+    for (; itemPtr->locale != NULL; itemPtr++) {
+        UPluralRules* uplrules;
+        UEnumeration* uenum;
+        UBool expectKeywords[kNumKeywords];
+        UBool getKeywords[kNumKeywords];
+        int32_t i, iKnown;
+        UErrorCode status = U_ZERO_ERROR;
+        
+        /* initialize arrays for expected and get results */
+        for (i = 0; i < kNumKeywords; i++) {
+            expectKeywords[i] = FALSE;
+            getKeywords[i] = FALSE;
+        }
+        for (i = 0; i < kNumKeywords && itemPtr->keywords[i] != NULL; i++) {
+            iKnown = getKeywordIndex(itemPtr->keywords[i]);
+            if (iKnown >= 0) {
+                expectKeywords[iKnown] = TRUE;
+            }
+        }
+        
+        uplrules = uplrules_openForType(itemPtr->locale, UPLURAL_TYPE_CARDINAL, &status);
+        if (U_FAILURE(status)) {
+            log_err("FAIL: uplrules_openForType for locale %s, UPLURAL_TYPE_CARDINAL: %s\n", itemPtr->locale, myErrorName(status) );
+            continue;
+        }
+        uenum = uplrules_getKeywords(uplrules, &status);
+        if (U_FAILURE(status)) {
+            log_err("FAIL: uplrules_getKeywords for locale %s: %s\n", itemPtr->locale, myErrorName(status) );
+        } else {
+            const char* keyword;
+            int32_t keywordLen, keywordCount = 0;
+            while ((keyword = uenum_next(uenum, &keywordLen, &status)) != NULL && U_SUCCESS(status)) {
+                iKnown = getKeywordIndex(keyword);
+                if (iKnown < 0) {
+                    log_err("FAIL: uplrules_getKeywords for locale %s, unknown keyword %s\n", itemPtr->locale, keyword );
+                } else {
+                    getKeywords[iKnown] = TRUE;
+                }
+                keywordCount++;
+            }
+            if (keywordCount > kNumKeywords) {
+                log_err("FAIL: uplrules_getKeywords for locale %s, got too many keywords %d\n", itemPtr->locale, keywordCount );
+            }
+            if (uprv_memcmp(expectKeywords, getKeywords, kNumKeywords) != 0) {
+                log_err("FAIL: uplrules_getKeywords for locale %s, got wrong keyword set; with reference to knownKeywords:\n"
+                        "        expected { %d %d %d %d %d %d },\n"
+                        "        got      { %d %d %d %d %d %d }\n", itemPtr->locale, 
+                        expectKeywords[0], expectKeywords[1], expectKeywords[2], expectKeywords[3], expectKeywords[4], expectKeywords[5],
+                        getKeywords[0], getKeywords[1], getKeywords[2], getKeywords[3], getKeywords[4], getKeywords[5] );
+            }
+            uenum_close(uenum);
+        }
+        
+        uplrules_close(uplrules);
+    }
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */