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