From d2e2530243f9eda5515444e0c0c83c1f4308bfa3 Mon Sep 17 00:00:00 2001 From: Lukasz Pik Date: Wed, 26 Jul 2017 11:49:22 +0200 Subject: [PATCH] [Base-utils][Plural rules][ACR-1045] Module added Change-Id: Ibf10079134aa7c736ae1a8596b5e26eca2ce839b Signed-off-by: Lukasz Pik --- src/CMakeLists.txt | 2 + src/include/utils_i18n.h | 61 ++++++ src/include/utils_i18n_plural_rules.h | 357 ++++++++++++++++++++++++++++++++++ src/include/utils_i18n_types.h | 26 +++ src/utils_i18n_plural_rules.cpp | 183 +++++++++++++++++ 5 files changed, 629 insertions(+) create mode 100644 src/include/utils_i18n_plural_rules.h create mode 100644 src/utils_i18n_plural_rules.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59e9643..589c843 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,7 @@ SET(BASEUTILS_SRCS utils_i18n_ubidi.c utils_i18n_uversion.c utils_i18n_uchar_iter.c + utils_i18n_plural_rules.cpp ) ADD_LIBRARY(${target_name} SHARED ${BASEUTILS_SRCS} @@ -87,5 +88,6 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_utmscale.h DESTI INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_ubidi.h DESTINATION ${INCLUDE_INSTALL_DIR}/base) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_uversion.h DESTINATION ${INCLUDE_INSTALL_DIR}/base) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_uchar_iter.h DESTINATION ${INCLUDE_INSTALL_DIR}/base) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_plural_rules.h DESTINATION ${INCLUDE_INSTALL_DIR}/base) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n.h DESTINATION ${INCLUDE_INSTALL_DIR}/base) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${pc_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/src/include/utils_i18n.h b/src/include/utils_i18n.h index 36020b3..22ec43b 100644 --- a/src/include/utils_i18n.h +++ b/src/include/utils_i18n.h @@ -45,6 +45,7 @@ #include #include #include +#include /** * @file utils_i18n.h @@ -83,6 +84,7 @@ extern "C" { * - ubidi * - uversion * - uchar iter + * - plural rules * * This module provides flexible generation of number or date format patterns and helps you format and parse dates/number for any locale. * The i18n module provides various features based on data from ICU. The following table shows the version of ICU used in each Tizen platform. @@ -217,6 +219,10 @@ extern "C" { * @ref CAPI_BASE_UTILS_I18N_UCHAR_ITER_MODULE * The Uchar Iterator module provides API for code unit iteration. * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * The Plural rules module Defines rules for mapping non-negative numeric values onto a small set of keywords. + * * * * @section CAPI_BASE_UTILS_I18N_MODULE_MAPPING_TABLE Mapping Table @@ -3733,6 +3739,61 @@ extern "C" { * #i18n_uchar_iter_set_state * UCharIteratorSetState * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_create + * PluralRules + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_destroy + * ~PluralRules + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_clone + * clone + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_create_rules_from_descr + * createRules + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_for_locale + * forLocale + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_select_int32 + * select + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_select_double + * select + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_get_keywords + * getKeywords + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_get_samples + * getSamples + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_is_keyword + * isKeyword + * + * + * @ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * #i18n_plural_rules_get_keyword_other + * getKeywordOther + * * */ diff --git a/src/include/utils_i18n_plural_rules.h b/src/include/utils_i18n_plural_rules.h new file mode 100644 index 0000000..121e8a9 --- /dev/null +++ b/src/include/utils_i18n_plural_rules.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTILS_I18N_PLURAL_RULES_H__ +#define __UTILS_I18N_PLURAL_RULES_H__ + +#include + +/** + * @file utils_i18n_plural_rules.h + * @version 0.1 + * @brief utils_i18n_plural_rules + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @ingroup CAPI_BASE_UTILS_I18N_MODULE + * @defgroup CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE PluralRules + * @brief Defines rules for mapping non-negative numeric values onto a small set of keywords. + * @section CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE_OVERVIEW Overview + * @details Rules are constructed from a text description, consisting of a series of + * keywords and conditions. The select method examines each condition in order and returns + * the keyword for the first condition that matches the number. + * If none match, default rule(other) is returned. + * For more information, details, and tips for writing rules, see the LDML spec, + * C.11 Language Plural Rules: http://www.unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules \n\n + * + * Examples:\n + * + * "one: n is 1; few: n in 2..4" \n + * This defines two rules, for 'one' and 'few'. The condition for 'one' is "n is 1" + * which means that the number must be equal to 1 for this condition to pass. + * The condition for 'few' is "n in 2..4" which means that the number must be + * between 2 and 4 inclusive for this condition to pass. + * All other numbers are assigned the keyword "other" by the default rule. + * + * "zero: n is 0; one: n is 1; zero: n mod 100 in 1..19" \n + * This illustrates that the same keyword can be defined multiple times. + * Each rule is examined in order, and the first keyword whose condition passes is the one returned. + * Also notes that a modulus is applied to n in the last rule. + * Thus its condition holds for 119, 219, 319... + * + * "one: n is 1; few: n mod 10 in 2..4 and n mod 100 not in 12..14" \n + * This illustrates conjunction and negation. The condition for 'few' has two parts, both of which must be met: + * "n mod 10 in 2..4" and "n mod 100 not in 12..14". The first part applies a modulus to n + * before the test as in the previous example. The second part applies a different modulus + * and also uses negation, thus it matches all numbers not in 12, 13, 14, 112, 113, 114, 212, 213, 214... + * + * Syntax: \n + * + * @code + * rules = rule (';' rule)* + * rule = keyword ':' condition + * keyword = + * condition = and_condition ('or' and_condition)* + * and_condition = relation ('and' relation)* + * relation = is_relation | in_relation | within_relation | 'n' + * is_relation = expr 'is' ('not')? value + * in_relation = expr ('not')? 'in' range_list + * within_relation = expr ('not')? 'within' range + * expr = ('n' | 'i' | 'f' | 'v' | 'j') ('mod' value)? + * range_list = (range | value) (',' range_list)* + * value = digit+ ('.' digit+)? + * digit = 0|1|2|3|4|5|6|7|8|9 + * range = value'..'value + * @endcode + * + * The i, f, and v values are defined as follows: \n + *
    + *
  • i to be the integer digits.
  • + *
  • f to be the visible fractional digits, as an integer.
  • + *
  • v to be the number of visible fraction digits.
  • + *
  • j is defined to only match integers. That is "j is 3" fails if v != 0 (eg for 3.1 or 3.0).
  • + *
+ * + * Examples are in the following table: \n + * + * @code + * n 1.0 1.00 1.3 1.03 1.23 + * + * i 1 1 1 1 1 + * + * f 0 0 3 3 23 + * + * v 1 2 2 2 2 + * @endcode + * + * The difference between 'in' and 'within' is that 'in' only includes integers in the specified range, + * while 'within' includes all values. Using 'within' with a range_list consisting entirely of values + * is the same as using 'in' (it's not an error). An "identifier" is a sequence of characters + * that do not have the Unicode Pattern_Syntax or Pattern_White_Space properties. + * The difference between 'in' and 'within' is that 'in' only includes integers in the specified range, + * while 'within' includes all values. Using 'within' with a range_list consisting entirely of values + * is the same as using 'in' (it's not an error). Keywords could be defined by users or from ICU locale data. + * There are 6 predefined values in ICU - 'zero', 'one', 'two', 'few', 'many' and 'other'. + * Callers need to check the value of keyword returned by select method. \n\n + * + * Example: + * + * @code + * char keyword[BUFSIZE] = { 0 }; + * int32_t number = 10 + * int32_t output_length = -1; + * i18n_plural_rules_select_int32(plural_rules, number, BUFSIZE, keyword, &output_length); + * if (strncmp(keyword, "one", output_length) == 0) { + * ... + * } + * else if ( ... ) + * @endcode + */ + +/** + * @addtogroup CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE + * @{ + */ + +/** + * @brief Creates a plural rules object. + * @since_tizen 4.0 + * @remarks The created object should be released by the caller with the + * i18n_plural_rules_destroy() function. + * + * @param[out] plural_rules The created plural rules object + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + * @retval #I18N_ERROR_OUT_OF_MEMORY Out of memory + */ +int i18n_plural_rules_create(i18n_plural_rules_h *plural_rules); + +/** + * @brief Destroys the plural rules object. + * @since_tizen 4.0 + * + * @param[in] plural_rules The plural rules object to destroy + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + */ +int i18n_plural_rules_destroy(i18n_plural_rules_h plural_rules); + +/** + * @brief Creates a polymorphic clone of the given @a plural_rules object. + * @since_tizen 4.0 + * @remarks The @a clone object should be released by the caller with the + * i18n_plural_rules_destroy() function. + * + * @param[in] plural_rules The plural rules object to be cloned + * @param[out] clone The created plural rules object + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + * @retval #I18N_ERROR_OUT_OF_MEMORY Out of memory + */ +int i18n_plural_rules_clone(i18n_plural_rules_h plural_rules, i18n_plural_rules_h *clone); + +/** + * @brief Creates a plural rules object from a description. + * @details If the description is not parsable, plural_rules will be @c NULL. + * @since_tizen 4.0 + * @remarks The created object should be released by the caller with the + * i18n_plural_rules_destroy() function. + * + * @param[in] description Rule description + * @param[out] plural_rules The created plural rules object + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + */ +int i18n_plural_rules_create_rules_from_descr(const char *description, i18n_plural_rules_h *plural_rules); + +/** + * @brief Provides access to the predefined plural rules object for a given locale and the plural type. + * @details If there's no predefined rules for this locale, the rules for the closest parent + * in the locale hierarchy that has one will be returned. + * The final fallback always returns the default 'other' rules. + * @since_tizen 4.0 + * @remarks The created object should be released by the caller with the + * i18n_plural_rules_destroy() function. + * + * @param[in] language The language of the locale + * @param[in] country The country of the locale + * @param[in] type The plural type (e.g., cardinal or ordinal) + * @param[out] plural_rules The pointer to the plural rules object for given locale + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + * @retval #I18N_ERROR_OUT_OF_MEMORY Out of memory + */ +int i18n_plural_rules_for_locale(const char *language, + const char *country, + i18n_uplural_type_e type, + i18n_plural_rules_h *plural_rules); + +/** + * @brief Returns the keyword of the first rule that applies to the given number. + * @details This function can be used with i18n_plural_rules_is_keyword() function to determine + * the keyword for default plural rules. + * @since_tizen 4.0 + * + * @param[in] plural_rules The plural rules object + * @param[in] number The number for which the rule has to be determined + * @param[in] output_buffer_size The size of the @a output_buffer buffer. + * If @a output_buffer_size <= 0 then output string is not + * insert to the @a output_buffer buffer and #I18N_ERROR_BUFFER_OVERFLOW + * is returned. + * @param[out] output_buffer The buffer to which formatted string will be inserted. + * Can be @c NULL if @a output_buffer_size <= 0. + * @param[out] output_length The length of the output string + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + * @retval #I18N_ERROR_BUFFER_OVERFLOW Buffer overflow + */ +int i18n_plural_rules_select_int32(i18n_plural_rules_h plural_rules, + int32_t number, + int32_t output_buffer_size, + i18n_uchar *output_buffer, + int32_t *output_length); + +/** + * @brief Returns the keyword of the first rule that applies to the given number. + * @details This function can be used with i18n_plural_rules_is_keyword() function to determine + * the keyword for default plural rules. + * @since_tizen 4.0 + * + * @param[in] plural_rules The plural rules object + * @param[in] number The number for which the rule has to be determined + * @param[in] output_buffer_size The size of the @a output_buffer buffer. + * If @a output_buffer_size <= 0 then output string is not + * insert to the @a output_buffer buffer and #I18N_ERROR_BUFFER_OVERFLOW + * is returned. + * @param[out] output_buffer The buffer to which formatted string will be inserted. + * Can be @c NULL if @a output_buffer_size <= 0. + * @param[out] output_length The length of the output string + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + * @retval #I18N_ERROR_BUFFER_OVERFLOW Buffer overflow + */ +int i18n_plural_rules_select_double(i18n_plural_rules_h plural_rules, + double number, + int32_t output_buffer_size, + i18n_uchar *output_buffer, + int32_t *output_length); + +/** + * @brief Returns a list of all rule keywords used in this plural rules object. + * @details The rule 'other' is always present by default. + * @since_tizen 4.0 + * @remarks The obtained @a string_enum object should be released by the caller + * with the i18n_uenumeration_destroy() function. + * + * @param[in] plural_rules The plural rules object + * @param[out] string_enum String enumeration containing keywords + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + */ +int i18n_plural_rules_get_keywords(i18n_plural_rules_h plural_rules, i18n_uenumeration_h *string_enum); + +/** + * @brief Gets sample values for which i18n_plural_rules_select_* functions would return the keyword. + * @details If the keyword is unknown, returns no values, but this is not an error. + * The number of returned values is typically small. + * @since_tizen 4.0 + * + * @param[in] plural_rules The plural rules object + * @param[in] keyword The keyword + * @param[out] dest Array into which to put the returned values. May be @c NULL if @a dest_capacity is 0 + * @param[in] dest_capacity The capacity of the array, must be at least 0 + * @param[out] count The count of values written. If more than @a dest_capacity samples are available, + * then only @a dest_capacity are written, and @a dest_capacity is returned as the count, + * rather than setting a #I18N_ERROR_BUFFER_OVERFLOW. + * (The actual number of keyword values could be unlimited.) + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + */ +int i18n_plural_rules_get_samples(i18n_plural_rules_h plural_rules, const char *keyword, double *dest, int32_t dest_capacity, int32_t *count); + +/** + * @brief Checks if the given keyword is defined in a plural rules object. + * @since_tizen 4.0 + * + * @param[in] plural_rules The plural rules object + * @param[in] keyword The input keyword + * @param[out] is_keyword Boolean value indicating if the given keyword is defined in @a plural_rules + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + */ +int i18n_plural_rules_is_keyword(i18n_plural_rules_h plural_rules, const char *keyword, i18n_ubool *is_keyword); + +/** + * @brief Returns keyword for default plural form. + * @since_tizen 4.0 + * + * @param[in] plural_rules The plural rules object + * @param[in] output_buffer_size The size of the @a output_buffer buffer. + * If @a output_buffer_size <= 0 then output string is not + * insert to the @a output_buffer buffer and #I18N_ERROR_BUFFER_OVERFLOW + * is returned. + * @param[out] output_buffer The buffer to which formatted string will be inserted. + * Can be @c NULL if @a output_buffer_size <= 0. + * @param[out] output_length The length of the output string + * + * @return @c 0 on success, otherwise a negative error value + * @retval #I18N_ERROR_NONE Successful + * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter + * @retval #I18N_ERROR_BUFFER_OVERFLOW Buffer overflow + */ +int i18n_plural_rules_get_keyword_other(i18n_plural_rules_h plural_rules, + int32_t output_buffer_size, + i18n_uchar *output_buffer, + int32_t *output_length); + + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __UTILS_I18N_PLURAL_RULES_H__*/ diff --git a/src/include/utils_i18n_types.h b/src/include/utils_i18n_types.h index a394cd4..4ec25a6 100644 --- a/src/include/utils_i18n_types.h +++ b/src/include/utils_i18n_types.h @@ -4264,6 +4264,32 @@ typedef enum { */ /** +* @addtogroup CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE +* @{ +*/ + +/** + * @brief An #i18n_plural_rules_h handle. + * @details Use i18n_plural_rules_* functions to operate on #i18n_plural_rules_h objects. + * @since_tizen 4.0 + */ +typedef void *i18n_plural_rules_h; + +/** + * @brief Type of plurals and plural rules objects. + * @since_tizen 4.0 + */ +typedef enum { + I18N_UPLURAL_TYPE_CARDINAL, /**< Plural rules for cardinal numbers: 1 file vs. 2 files */ + I18N_UPLURAL_TYPE_ORDINAL, /**< Plural rules for ordinal numbers: + 1st file, 2nd file, 3rd file, 4th file, etc. */ +} i18n_uplural_type_e; + +/** + * @} + */ + +/** * @brief This value is intended for sentinel values for APIs that (take or) return * single code points (#i18n_uchar32). * @details It is outside of the Unicode code point range 0..0x10ffff. For example, diff --git a/src/utils_i18n_plural_rules.cpp b/src/utils_i18n_plural_rules.cpp new file mode 100644 index 0000000..4feb629 --- /dev/null +++ b/src/utils_i18n_plural_rules.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include + +int i18n_plural_rules_create(i18n_plural_rules_h *plural_rules) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + + UErrorCode status = U_ZERO_ERROR; + *plural_rules = new PluralRules(status); + + retv_if(*plural_rules == NULL, I18N_ERROR_OUT_OF_MEMORY); + return _i18n_error_mapping(status); +} + +int i18n_plural_rules_destroy(i18n_plural_rules_h plural_rules) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + + delete((PluralRules *) plural_rules); + + return I18N_ERROR_NONE; +} + +int i18n_plural_rules_clone(i18n_plural_rules_h plural_rules, i18n_plural_rules_h *clone) +{ + retv_if(plural_rules == NULL || clone == NULL, I18N_ERROR_INVALID_PARAMETER); + + *clone = ((PluralRules *) plural_rules)->clone(); + retv_if(*clone == NULL, I18N_ERROR_OUT_OF_MEMORY); + + return I18N_ERROR_NONE; +} + +int i18n_plural_rules_create_rules_from_descr(const char *description, i18n_plural_rules_h *plural_rules) +{ + retv_if(description == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + UErrorCode status = U_ZERO_ERROR; + UnicodeString unicode_description(description); + + *plural_rules = PluralRules::createRules(unicode_description, status); + + return _i18n_error_mapping(status); +} + +int i18n_plural_rules_for_locale(const char *language, + const char *country, + i18n_uplural_type_e type, + i18n_plural_rules_h *plural_rules) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + + UErrorCode status = U_ZERO_ERROR; + *plural_rules = PluralRules::forLocale(Locale(language, country, 0, 0), (UPluralType)type, status); + + return _i18n_error_mapping(status); +} + +int i18n_plural_rules_select_int32(i18n_plural_rules_h plural_rules, + int32_t number, + int32_t append_to_size, + i18n_uchar *append_to, + int32_t *output_length) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(output_length == NULL, I18N_ERROR_INVALID_PARAMETER); + + UnicodeString result = ((PluralRules *)plural_rules)->select(number); + + const i18n_uchar *uchar_result = (i18n_uchar *)result.getTerminatedBuffer(); + + retv_if(uchar_result == NULL, I18N_ERROR_INVALID_PARAMETER); + + *output_length = i18n_ustring_get_length(uchar_result); + retv_if(append_to_size < *output_length, I18N_ERROR_BUFFER_OVERFLOW); + + if (*output_length > 0) + i18n_ustring_copy_n(append_to, uchar_result, append_to_size); + + return I18N_ERROR_NONE; +} + +int i18n_plural_rules_select_double(i18n_plural_rules_h plural_rules, + double number, + int32_t append_to_size, + i18n_uchar *append_to, + int32_t *output_length) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(output_length == NULL, I18N_ERROR_INVALID_PARAMETER); + + UnicodeString result = ((PluralRules *)plural_rules)->select(number); + + const i18n_uchar *uchar_result = (i18n_uchar *)result.getTerminatedBuffer(); + + retv_if(uchar_result == NULL, I18N_ERROR_INVALID_PARAMETER); + + *output_length = i18n_ustring_get_length(uchar_result); + retv_if(append_to_size < *output_length, I18N_ERROR_BUFFER_OVERFLOW); + + if (*output_length > 0) + i18n_ustring_copy_n(append_to, uchar_result, append_to_size); + + return I18N_ERROR_NONE; +} + +int i18n_plural_rules_get_keywords(i18n_plural_rules_h plural_rules, i18n_uenumeration_h *string_enum) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(string_enum == NULL, I18N_ERROR_INVALID_PARAMETER); + + UErrorCode status = U_ZERO_ERROR; + *string_enum = ((PluralRules *)plural_rules)->getKeywords(status); + + return _i18n_error_mapping(status); +} + +int i18n_plural_rules_get_samples(i18n_plural_rules_h plural_rules, const char *keyword, double *dest, int32_t dest_capacity, int32_t *count) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(dest == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(dest_capacity < 0, I18N_ERROR_INVALID_PARAMETER); + retv_if(count == NULL, I18N_ERROR_INVALID_PARAMETER); + + UErrorCode status = U_ZERO_ERROR; + UnicodeString unicode_keyword(keyword); + + *count = ((PluralRules *)plural_rules)->getSamples(unicode_keyword, dest, dest_capacity, status); + + return _i18n_error_mapping(status); +} + +int i18n_plural_rules_is_keyword(i18n_plural_rules_h plural_rules, const char *keyword, i18n_ubool *is_keyword) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(is_keyword == NULL, I18N_ERROR_INVALID_PARAMETER); + + *is_keyword = ((PluralRules *)plural_rules)->isKeyword(keyword); + + return I18N_ERROR_NONE; +} + +int i18n_plural_rules_get_keyword_other(i18n_plural_rules_h plural_rules, + int32_t append_to_size, + i18n_uchar *append_to, + int32_t *output_length) +{ + retv_if(plural_rules == NULL, I18N_ERROR_INVALID_PARAMETER); + retv_if(output_length == NULL, I18N_ERROR_INVALID_PARAMETER); + + UnicodeString result = ((PluralRules *)plural_rules)->getKeywordOther(); + + const i18n_uchar *uchar_result = (i18n_uchar *)result.getTerminatedBuffer(); + + retv_if(uchar_result == NULL, I18N_ERROR_INVALID_PARAMETER); + + *output_length = i18n_ustring_get_length(uchar_result); + retv_if(append_to_size < *output_length, I18N_ERROR_BUFFER_OVERFLOW); + + if (*output_length > 0) + i18n_ustring_copy_n(append_to, uchar_result, append_to_size); + + return I18N_ERROR_NONE; +} -- 2.7.4