| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /* |
| ***************************************************************************************** |
| * Copyright (C) 2010-2012, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| ***************************************************************************************** |
| */ |
| |
| #include "unicode/utypes.h" |
| |
| #include <cstring> |
| |
| #if !UCONFIG_NO_FORMATTING |
| |
| #include "unicode/upluralrules.h" |
| #include "unicode/plurrule.h" |
| #include "unicode/locid.h" |
| #include "unicode/unistr.h" |
| #include "unicode/unum.h" |
| #include "unicode/numfmt.h" |
| #include "unicode/unumberformatter.h" |
| #include "number_decimalquantity.h" |
| #include "number_utypes.h" |
| #include "numrange_impl.h" |
| |
| U_NAMESPACE_USE |
| |
| namespace { |
| |
| /** |
| * Given a number and a format, returns the keyword of the first applicable |
| * rule for the PluralRules object. |
| * @param rules The plural rules. |
| * @param obj The numeric object for which the rule should be determined. |
| * @param fmt The NumberFormat specifying how the number will be formatted |
| * (this can affect the plural form, e.g. "1 dollar" vs "1.0 dollars"). |
| * @param status Input/output parameter. If at entry this indicates a |
| * failure status, the method returns immediately; otherwise |
| * this is set to indicate the outcome of the call. |
| * @return The keyword of the selected rule. Undefined in the case of an error. |
| */ |
| UnicodeString select(const PluralRules &rules, const Formattable& obj, const NumberFormat& fmt, UErrorCode& status) { |
| if (U_SUCCESS(status)) { |
| const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt); |
| if (decFmt != NULL) { |
| number::impl::DecimalQuantity dq; |
| decFmt->formatToDecimalQuantity(obj, dq, status); |
| if (U_SUCCESS(status)) { |
| return rules.select(dq); |
| } |
| } else { |
| double number = obj.getDouble(status); |
| if (U_SUCCESS(status)) { |
| return rules.select(number); |
| } |
| } |
| } |
| return UnicodeString(); |
| } |
| |
| } // namespace |
| |
| U_CAPI UPluralRules* U_EXPORT2 |
| uplrules_open(const char *locale, UErrorCode *status) |
| { |
| return uplrules_openForType(locale, UPLURAL_TYPE_CARDINAL, status); |
| } |
| |
| U_CAPI UPluralRules* U_EXPORT2 |
| uplrules_openForType(const char *locale, UPluralType type, UErrorCode *status) |
| { |
| return (UPluralRules*)PluralRules::forLocale(Locale(locale), type, *status); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| uplrules_close(UPluralRules *uplrules) |
| { |
| delete (PluralRules*)uplrules; |
| } |
| |
| U_CAPI int32_t U_EXPORT2 |
| uplrules_select(const UPluralRules *uplrules, |
| double number, |
| UChar *keyword, int32_t capacity, |
| UErrorCode *status) |
| { |
| if (U_FAILURE(*status)) { |
| return 0; |
| } |
| if (keyword == NULL ? capacity != 0 : capacity < 0) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return 0; |
| } |
| UnicodeString result = ((PluralRules*)uplrules)->select(number); |
| return result.extract(keyword, capacity, *status); |
| } |
| |
| U_CAPI int32_t U_EXPORT2 |
| uplrules_selectFormatted(const UPluralRules *uplrules, |
| const UFormattedNumber* number, |
| UChar *keyword, int32_t capacity, |
| UErrorCode *status) |
| { |
| if (U_FAILURE(*status)) { |
| return 0; |
| } |
| if (keyword == NULL ? capacity != 0 : capacity < 0) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return 0; |
| } |
| const number::impl::DecimalQuantity* dq = |
| number::impl::validateUFormattedNumberToDecimalQuantity(number, *status); |
| if (U_FAILURE(*status)) { |
| return 0; |
| } |
| UnicodeString result = ((PluralRules*)uplrules)->select(*dq); |
| return result.extract(keyword, capacity, *status); |
| } |
| |
| U_CAPI int32_t U_EXPORT2 |
| uplrules_selectForRange(const UPluralRules *uplrules, |
| const UFormattedNumberRange* urange, |
| UChar *keyword, int32_t capacity, |
| UErrorCode *status) |
| { |
| if (U_FAILURE(*status)) { |
| return 0; |
| } |
| if (keyword == NULL ? capacity != 0 : capacity < 0) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return 0; |
| } |
| const number::impl::UFormattedNumberRangeData* impl = |
| number::impl::validateUFormattedNumberRange(urange, *status); |
| UnicodeString result = ((PluralRules*)uplrules)->select(impl, *status); |
| return result.extract(keyword, capacity, *status); |
| } |
| |
| U_CAPI int32_t U_EXPORT2 |
| uplrules_selectWithFormat(const UPluralRules *uplrules, |
| double number, |
| const UNumberFormat *fmt, |
| UChar *keyword, int32_t capacity, |
| UErrorCode *status) |
| { |
| if (U_FAILURE(*status)) { |
| return 0; |
| } |
| const PluralRules* plrules = reinterpret_cast<const PluralRules*>(uplrules); |
| const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
| if (plrules == NULL || nf == NULL || ((keyword == NULL)? capacity != 0 : capacity < 0)) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return 0; |
| } |
| Formattable obj(number); |
| UnicodeString result = select(*plrules, obj, *nf, *status); |
| 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 */ |