[Base-utils][Plural rules][ACR-1045] Module added 16/140816/21
authorLukasz Pik <lu.pik@partner.samsung.com>
Wed, 26 Jul 2017 09:49:22 +0000 (11:49 +0200)
committerhyunjee Kim <hj0426.kim@samsung.com>
Mon, 21 Aug 2017 00:44:07 +0000 (00:44 +0000)
Change-Id: Ibf10079134aa7c736ae1a8596b5e26eca2ce839b
Signed-off-by: Lukasz Pik <lu.pik@partner.samsung.com>
src/CMakeLists.txt
src/include/utils_i18n.h
src/include/utils_i18n_plural_rules.h [new file with mode: 0644]
src/include/utils_i18n_types.h
src/utils_i18n_plural_rules.cpp [new file with mode: 0644]

index 59e9643..589c843 100755 (executable)
@@ -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)
index 36020b3..22ec43b 100644 (file)
@@ -45,6 +45,7 @@
 #include <utils_i18n_ubidi.h>
 #include <utils_i18n_uversion.h>
 #include <utils_i18n_uchar_iter.h>
+#include <utils_i18n_plural_rules.h>
 
 /**
  * @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" {
  *     <td>@ref CAPI_BASE_UTILS_I18N_UCHAR_ITER_MODULE</td>
  *     <td>The Uchar Iterator module provides API for code unit iteration.</td>
  * </tr>
+ * <tr>
+ *     <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *     <td>The Plural rules module Defines rules for mapping non-negative numeric values onto a small set of keywords.</td>
+ * </tr>
  * </table>
  *
  * @section CAPI_BASE_UTILS_I18N_MODULE_MAPPING_TABLE Mapping Table
@@ -3733,6 +3739,61 @@ extern "C" {
  *    <td>#i18n_uchar_iter_set_state</td>
  *    <td>UCharIteratorSetState</td>
  * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_create</td>
+ *    <td>PluralRules</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_destroy</td>
+ *    <td>~PluralRules</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_clone</td>
+ *    <td>clone</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_create_rules_from_descr</td>
+ *    <td>createRules</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_for_locale</td>
+ *    <td>forLocale</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_select_int32</td>
+ *    <td>select</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_select_double</td>
+ *    <td>select</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_get_keywords</td>
+ *    <td>getKeywords</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_get_samples</td>
+ *    <td>getSamples</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_is_keyword</td>
+ *    <td>isKeyword</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_PLURAL_RULES_MODULE</td>
+ *    <td>#i18n_plural_rules_get_keyword_other</td>
+ *    <td>getKeywordOther</td>
+ * </tr>
  * </table>
  */
 
diff --git a/src/include/utils_i18n_plural_rules.h b/src/include/utils_i18n_plural_rules.h
new file mode 100644 (file)
index 0000000..121e8a9
--- /dev/null
@@ -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 <utils_i18n_types.h>
+
+/**
+ * @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 <utils_i18n.h>
+ *
+ * @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         = <identifier>
+ *          condition       = and_condition ('or' and_condition)*
+ *          and_condition   = relation ('and' relation)*
+ *          relation        = is_relation | in_relation | within_relation | 'n' <EOL>
+ *          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
+ *          <ul>
+ *              <li> i to be the integer digits. </li>
+ *              <li> f to be the visible fractional digits, as an integer. </li>
+ *              <li> v to be the number of visible fraction digits. </li>
+ *              <li> j is defined to only match integers. That is "j is 3" fails if v != 0 (eg for 3.1 or 3.0). </li>
+ *          </ul>
+ *
+ *          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 <code>@a output_buffer_size <= 0</code> 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 <code>@a output_buffer_size <= 0</code>.
+ * @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 <code>@a output_buffer_size <= 0</code> 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 <code>@a output_buffer_size <= 0</code>.
+ * @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 <code>@a output_buffer_size <= 0</code> 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 <code>@a output_buffer_size <= 0</code>.
+ * @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__*/
index a394cd4..4ec25a6 100644 (file)
@@ -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 (file)
index 0000000..4feb629
--- /dev/null
@@ -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 <utils_i18n_plural_rules.h>
+#include <utils_i18n_ustring.h>
+#include <utils_i18n_private.h>
+
+#include <unicode/plurrule.h>
+
+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;
+}