Home | History | Annotate | Download | only in i18n
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *****************************************************************************************
      5 * Copyright (C) 2010-2012, International Business Machines
      6 * Corporation and others. All Rights Reserved.
      7 *****************************************************************************************
      8 */
      9 
     10 #include "unicode/utypes.h"
     11 
     12 #if !UCONFIG_NO_FORMATTING
     13 
     14 #include "unicode/upluralrules.h"
     15 #include "unicode/plurrule.h"
     16 #include "unicode/locid.h"
     17 #include "unicode/unistr.h"
     18 #include "unicode/unum.h"
     19 #include "unicode/numfmt.h"
     20 #include "number_decimalquantity.h"
     21 
     22 U_NAMESPACE_USE
     23 
     24 namespace {
     25 
     26 /**
     27  * Given a number and a format, returns the keyword of the first applicable
     28  * rule for the PluralRules object.
     29  * @param rules The plural rules.
     30  * @param obj The numeric object for which the rule should be determined.
     31  * @param fmt The NumberFormat specifying how the number will be formatted
     32  *        (this can affect the plural form, e.g. "1 dollar" vs "1.0 dollars").
     33  * @param status  Input/output parameter. If at entry this indicates a
     34  *                failure status, the method returns immediately; otherwise
     35  *                this is set to indicate the outcome of the call.
     36  * @return The keyword of the selected rule. Undefined in the case of an error.
     37  */
     38 UnicodeString select(const PluralRules &rules, const Formattable& obj, const NumberFormat& fmt, UErrorCode& status) {
     39     if (U_SUCCESS(status)) {
     40         const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
     41         if (decFmt != NULL) {
     42             number::impl::DecimalQuantity dq;
     43             decFmt->formatToDecimalQuantity(obj, dq, status);
     44             if (U_SUCCESS(status)) {
     45                 return rules.select(dq);
     46             }
     47         } else {
     48             double number = obj.getDouble(status);
     49             if (U_SUCCESS(status)) {
     50                 return rules.select(number);
     51             }
     52         }
     53     }
     54     return UnicodeString();
     55 }
     56 
     57 }  // namespace
     58 
     59 U_CAPI UPluralRules* U_EXPORT2
     60 uplrules_open(const char *locale, UErrorCode *status)
     61 {
     62     return uplrules_openForType(locale, UPLURAL_TYPE_CARDINAL, status);
     63 }
     64 
     65 U_CAPI UPluralRules* U_EXPORT2
     66 uplrules_openForType(const char *locale, UPluralType type, UErrorCode *status)
     67 {
     68     return (UPluralRules*)PluralRules::forLocale(Locale(locale), type, *status);
     69 }
     70 
     71 U_CAPI void U_EXPORT2
     72 uplrules_close(UPluralRules *uplrules)
     73 {
     74     delete (PluralRules*)uplrules;
     75 }
     76 
     77 U_CAPI int32_t U_EXPORT2
     78 uplrules_select(const UPluralRules *uplrules,
     79                 double number,
     80                 UChar *keyword, int32_t capacity,
     81                 UErrorCode *status)
     82 {
     83     if (U_FAILURE(*status)) {
     84         return 0;
     85     }
     86     if (keyword == NULL ? capacity != 0 : capacity < 0) {
     87         *status = U_ILLEGAL_ARGUMENT_ERROR;
     88         return 0;
     89     }
     90     UnicodeString result = ((PluralRules*)uplrules)->select(number);
     91     return result.extract(keyword, capacity, *status);
     92 }
     93 
     94 U_CAPI int32_t U_EXPORT2
     95 uplrules_selectWithFormat(const UPluralRules *uplrules,
     96                           double number,
     97                           const UNumberFormat *fmt,
     98                           UChar *keyword, int32_t capacity,
     99                           UErrorCode *status)
    100 {
    101     if (U_FAILURE(*status)) {
    102         return 0;
    103     }
    104     const PluralRules* plrules = reinterpret_cast<const PluralRules*>(uplrules);
    105     const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
    106     if (plrules == NULL || nf == NULL || ((keyword == NULL)? capacity != 0 : capacity < 0)) {
    107         *status = U_ILLEGAL_ARGUMENT_ERROR;
    108         return 0;
    109     }
    110     Formattable obj(number);
    111     UnicodeString result = select(*plrules, obj, *nf, *status);
    112     return result.extract(keyword, capacity, *status);
    113 }
    114 
    115 U_CAPI UEnumeration* U_EXPORT2
    116 uplrules_getKeywords(const UPluralRules *uplrules,
    117                      UErrorCode *status)
    118 {
    119     if (U_FAILURE(*status)) {
    120         return NULL;
    121     }
    122     const PluralRules* plrules = reinterpret_cast<const PluralRules*>(uplrules);
    123     if (plrules == NULL) {
    124         *status = U_ILLEGAL_ARGUMENT_ERROR;
    125         return NULL;
    126     }
    127     StringEnumeration *senum = plrules->getKeywords(*status);
    128     if (U_FAILURE(*status)) {
    129         return NULL;
    130     }
    131     if (senum == NULL) {
    132         *status = U_MEMORY_ALLOCATION_ERROR;
    133         return NULL;
    134     }
    135     return uenum_openFromStringEnumeration(senum, status);
    136 }
    137 
    138 #endif /* #if !UCONFIG_NO_FORMATTING */
    139