|  | // © 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 */ |