diff --git a/.gitattributes b/.gitattributes index d15c513fefe..b7e48fd8173 100644 --- a/.gitattributes +++ b/.gitattributes @@ -83,7 +83,9 @@ icu4c/source/extra/uconv/uconv.vcxproj -text icu4c/source/extra/uconv/uconv.vcxproj.filters -text icu4c/source/i18n/i18n.vcxproj -text icu4c/source/i18n/i18n.vcxproj.filters -text +icu4c/source/i18n/unicode/unumsys.h -text icu4c/source/i18n/unicode/uregion.h -text +icu4c/source/i18n/unumsys.cpp -text icu4c/source/i18n/uregion.cpp -text icu4c/source/io/io.vcxproj -text icu4c/source/io/io.vcxproj.filters -text diff --git a/icu4c/source/i18n/Makefile.in b/icu4c/source/i18n/Makefile.in index c908801dd7f..2b8bc89e70f 100644 --- a/icu4c/source/i18n/Makefile.in +++ b/icu4c/source/i18n/Makefile.in @@ -66,7 +66,7 @@ OBJECTS = ucln_in.o \ fmtable.o format.o msgfmt.o umsg.o numfmt.o unum.o decimfmt.o dcfmtsym.o \ ucurr.o digitlst.o fmtable_cnv.o \ choicfmt.o datefmt.o smpdtfmt.o reldtfmt.o dtfmtsym.o udat.o dtptngen.o udatpg.o \ -nfrs.o nfrule.o nfsubs.o rbnf.o numsys.o ucsdet.o \ +nfrs.o nfrule.o nfsubs.o rbnf.o numsys.o unumsys.o ucsdet.o \ ucal.o calendar.o gregocal.o timezone.o simpletz.o olsontz.o \ astro.o taiwncal.o buddhcal.o persncal.o islamcal.o japancal.o gregoimp.o hebrwcal.o \ indiancal.o chnsecal.o cecal.o coptccal.o dangical.o ethpccal.o \ diff --git a/icu4c/source/i18n/i18n.vcxproj b/icu4c/source/i18n/i18n.vcxproj index fc33d41529b..3c1eebb04c3 100644 --- a/icu4c/source/i18n/i18n.vcxproj +++ b/icu4c/source/i18n/i18n.vcxproj @@ -344,6 +344,7 @@ + @@ -1402,6 +1403,20 @@ ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + + + copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + copy "%(FullPath)" ..\..\include\unicode ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) diff --git a/icu4c/source/i18n/i18n.vcxproj.filters b/icu4c/source/i18n/i18n.vcxproj.filters index c8fe93e73e5..da3b9aa8665 100644 --- a/icu4c/source/i18n/i18n.vcxproj.filters +++ b/icu4c/source/i18n/i18n.vcxproj.filters @@ -291,6 +291,9 @@ formatting + + formatting + formatting @@ -993,6 +996,9 @@ formatting + + formatting + formatting diff --git a/icu4c/source/i18n/unicode/unumsys.h b/icu4c/source/i18n/unicode/unumsys.h new file mode 100644 index 00000000000..bf26b226aeb --- /dev/null +++ b/icu4c/source/i18n/unicode/unumsys.h @@ -0,0 +1,137 @@ +/* +***************************************************************************************** +* Copyright (C) 2013, International Business Machines +* Corporation and others. All Rights Reserved. +***************************************************************************************** +*/ + +#ifndef UNUMSYS_H +#define UNUMSYS_H + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/uenum.h" +#include "unicode/localpointer.h" + +/** + * \file + * \brief C API: UNumberingSystem, information about numbering systems + * + * Defines numbering systems. A numbering system describes the scheme by which + * numbers are to be presented to the end user. In its simplest form, a numbering + * system describes the set of digit characters that are to be used to display + * numbers, such as Western digits, Thai digits, Arabic-Indic digits, etc. + * More complicated numbering systems are algorithmic in nature, and require use + * of an RBNF formatter (rule based number formatter), in order to calculate + * the characters to be displayed for a given number. Examples of algorithmic + * numbering systems include Roman numerals, Chinese numerals, and Hebrew numerals. + * Formatting rules for many commonly used numbering systems are included in + * the ICU package, based on the numbering system rules defined in CLDR. + * Alternate numbering systems can be specified to a locale by using the + * numbers locale keyword. + */ + +#ifndef U_HIDE_DRAFT_API + +/** + * Opaque UNumberingSystem object for use in C programs. + * @draft ICU 52 + */ +struct UNumberingSystem; +typedef struct UNumberingSystem UNumberingSystem; /**< C typedef for struct UNumberingSystem. @draft ICU 52 */ + +/** + * Opens a UNumberingSystem object using the default numbering system for the specified locale. + * @param locale The locale for which the default numbering system should be opened. + * @param status A pointer to a UErrorCode to receive any errors. For example, this may be U_UNSUPPORTED_ERROR + * for a locale such as "en@numbers=xyz" that specifies a numbering system unknown to ICU. + * @return A UNumberingSystem for the specified locale, or NULL if an error occurred. + * @draft ICU 52 + */ +U_DRAFT UNumberingSystem * U_EXPORT2 +unumsys_open(const char *locale, UErrorCode *status); + +/** + * Opens a UNumberingSystem object using the name of one of the predefined numbering systems defined by CLDR + * and known to ICU, such as "latn", "arabext", or "hanidec"; the full list is returned by unumsys_openAvailableNames. + * Note that some of the numbering systems names listed at + * http://unicode.org/repos/cldr/tags/latest/common/bcp47/number.xml + * do not identify specific numbering systems, but rather types that may only be used as part of a locale which + * defines how they are mapped to a specific numbering system such as "latn" or "hant". + * + * @param name The name of the numbering system for which a UNumberingSystem object should be opened. + * @param status A pointer to a UErrorCode to receive any errors. For example, this may be U_UNSUPPORTED_ERROR + * for a numbering system such as "xyz" that is unknown to ICU. + * @return A UNumberingSystem for the specified name, or NULL if an error occurred. + * @draft ICU 52 + */ +U_DRAFT UNumberingSystem * U_EXPORT2 +unumsys_openByName(const char *name, UErrorCode *status); + +/** + * Close a UNumberingSystem object. Once closed it may no longer be used. + * @param unumsys The UNumberingSystem object to close. + * @draft ICU 52 + */ +U_DRAFT void U_EXPORT2 +unumsys_close(UNumberingSystem *unumsys); + +#if U_SHOW_CPLUSPLUS_API +U_NAMESPACE_BEGIN + +/** + * \class LocalUNumberingSystemPointer + * "Smart pointer" class, closes a UNumberingSystem via unumsys_close(). + * For most methods see the LocalPointerBase base class. + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 52 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUNumberingSystemPointer, UNumberingSystem, unumsys_close); + +U_NAMESPACE_END +#endif + +/** + * Returns an enumeration over the names of all of the predefined numbering systems known to ICU. + * @param status A pointer to a UErrorCode to receive any errors. + * @return A pointer to a UEnumeration that must be closed with uenum_close(), or NULL if an error occurred. + * @draft ICU 52 + */ +U_DRAFT UEnumeration * U_EXPORT2 +unumsys_openAvailableNames(UErrorCode *status); + +/** + * Returns the name of the specified UNumberingSystem object (if it is one of the predefined names known to ICU). + * @param unumsys The UNumberingSystem whose name is desired. + * @return A pointer to the name of the specified UNumberingSystem object, or NULL if the name is not one of the ICU predefined names. + * @draft ICU 52 + */ +U_DRAFT const char * U_EXPORT2 +unumsys_getName(UNumberingSystem *unumsys); + +/** + * Returns the radix of the specified UNumberingSystem object. + * @param unumsys The UNumberingSystem whose radix is desired. + * @return The radix of the specified UNumberingSystem object. + * @draft ICU 52 + */ +U_DRAFT int32_t U_EXPORT2 +unumsys_getRadix(UNumberingSystem *unumsys); + +/** + * Returns whether the given UNumberingSystem object is for an algorithmic (not purely decimal) system. + * @param unumsys The UNumberingSystem whose algorithmic status is desired. + * @return TRUE if the specified UNumberingSystem object is for an algorithmic system. + * @draft ICU 52 + */ +U_DRAFT UBool U_EXPORT2 +unumsys_isAlgorithmic(UNumberingSystem *unumsys); + +#endif /* U_HIDE_DRAFT_API */ + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/icu4c/source/i18n/unumsys.cpp b/icu4c/source/i18n/unumsys.cpp new file mode 100644 index 00000000000..f8eb6c7d654 --- /dev/null +++ b/icu4c/source/i18n/unumsys.cpp @@ -0,0 +1,68 @@ +/* +***************************************************************************************** +* Copyright (C) 2013, International Business Machines Corporation and others. +* All Rights Reserved. +***************************************************************************************** +*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/unumsys.h" +#include "unicode/numsys.h" +#include "unicode/uenum.h" + +U_NAMESPACE_USE + + +U_CAPI UNumberingSystem* U_EXPORT2 +unumsys_open(const char *locale, UErrorCode *status) +{ + return (UNumberingSystem*)NumberingSystem::createInstance(Locale(locale), *status); +} + + +U_CAPI UNumberingSystem* U_EXPORT2 +unumsys_openByName(const char *name, UErrorCode *status) +{ + return (UNumberingSystem*)NumberingSystem::createInstanceByName(name, *status); +} + + +U_CAPI void U_EXPORT2 +unumsys_close(UNumberingSystem *unumsys) +{ + delete ((NumberingSystem*)unumsys); +} + + +U_CAPI UEnumeration* U_EXPORT2 +unumsys_openAvailableNames(UErrorCode *status) +{ + return uenum_openFromStringEnumeration(NumberingSystem::getAvailableNames(*status), status); +} + + +U_CAPI const char * U_EXPORT2 +unumsys_getName(UNumberingSystem *unumsys) +{ + return ((NumberingSystem*)unumsys)->getName(); +} + + +U_CAPI int32_t U_EXPORT2 +unumsys_getRadix(UNumberingSystem *unumsys) +{ + return ((NumberingSystem*)unumsys)->getRadix(); +} + + +U_CAPI UBool U_EXPORT2 +unumsys_isAlgorithmic(UNumberingSystem *unumsys) +{ + return ((NumberingSystem*)unumsys)->isAlgorithmic(); +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/test/cintltst/cnumtst.c b/icu4c/source/test/cintltst/cnumtst.c index e2bdbc3978e..7898f36e786 100644 --- a/icu4c/source/test/cintltst/cnumtst.c +++ b/icu4c/source/test/cintltst/cnumtst.c @@ -26,11 +26,13 @@ #include "unicode/uloc.h" #include "unicode/umisc.h" #include "unicode/unum.h" +#include "unicode/unumsys.h" #include "unicode/ustring.h" #include "cintltst.h" #include "cnumtst.h" #include "cmemory.h" +#include "cstring.h" #include "putilimp.h" #include @@ -52,6 +54,7 @@ static void TestParseCurrency(void); static void TestMaxInt(void); static void TestNoExponent(void); static void TestUFormattable(void); +static void TestUNumberingSystem(void); #define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x) @@ -75,6 +78,7 @@ void addNumForTest(TestNode** root) TESTCASE(TestMaxInt); TESTCASE(TestNoExponent); TESTCASE(TestUFormattable); + TESTCASE(TestUNumberingSystem); } /* test Parse int 64 */ @@ -2284,4 +2288,76 @@ static void TestUFormattable(void) { } } +typedef struct { + const char * locale; + const char * numsys; + int32_t radix; + UBool isAlgorithmic; +} NumSysTestItem; + +static const NumSysTestItem numSysTestItems[] = { + //locale numsys radix isAlgorithmic + { "en", "latn", 10, FALSE }, + { "en@numbers=roman", "roman", 10, TRUE }, + { "en@numbers=finance", "latn", 10, FALSE }, + { "ar", "arab", 10, FALSE }, + { "fa", "arabext", 10, FALSE }, + { "zh_Hant@numbers=traditional", "hant", 10, TRUE }, + { NULL, NULL, 0, FALSE }, +}; + +static void TestUNumberingSystem(void) { + const NumSysTestItem * itemPtr; + UNumberingSystem * unumsys; + UEnumeration * uenum; + const char * numsys; + UErrorCode status; + + for (itemPtr = numSysTestItems; itemPtr->locale != NULL; itemPtr++) { + status = U_ZERO_ERROR; + unumsys = unumsys_open(itemPtr->locale, &status); + if ( U_SUCCESS(status) ) { + int32_t radix = unumsys_getRadix(unumsys); + UBool isAlgorithmic = unumsys_isAlgorithmic(unumsys); + numsys = unumsys_getName(unumsys); + if ( uprv_strcmp(numsys, itemPtr->numsys) != 0 || radix != itemPtr->radix || !isAlgorithmic != !itemPtr->isAlgorithmic ) { + log_err("unumsys name/radix/isAlgorithmic for locale %s, expected %s/%d/%d, got %s/%d/%d\n", + itemPtr->locale, itemPtr->numsys, itemPtr->radix, itemPtr->isAlgorithmic, numsys, radix, isAlgorithmic); + } + unumsys_close(unumsys); + } else { + log_data_err("unumsys_open for locale %s fails with status %s\n", itemPtr->locale, myErrorName(status)); + } + } + + status = U_ZERO_ERROR; + uenum = unumsys_openAvailableNames(&status); + if ( U_SUCCESS(status) ) { + int32_t numsysCount = 0; + // sanity check for a couple of number systems that must be in the enumeration + UBool foundLatn = FALSE; + UBool foundArab = FALSE; + while ( (numsys = uenum_next(uenum, NULL, &status)) != NULL && U_SUCCESS(status) ) { + status = U_ZERO_ERROR; + unumsys = unumsys_openByName(numsys, &status); + if ( U_SUCCESS(status) ) { + numsysCount++; + if ( uprv_strcmp(numsys, "latn") ) foundLatn = TRUE; + if ( uprv_strcmp(numsys, "arab") ) foundArab = TRUE; + unumsys_close(unumsys); + } else { + log_err("unumsys_openAvailableNames includes %s but unumsys_openByName on it fails with status %s\n", + numsys, myErrorName(status)); + } + } + uenum_close(uenum); + if ( numsysCount < 40 || !foundLatn || !foundArab ) { + log_err("unumsys_openAvailableNames results incomplete: numsysCount %d, foundLatn %d, foundArab %d\n", + numsysCount, foundLatn, foundArab); + } + } else { + log_data_err("unumsys_openAvailableNames fails with status %s\n", myErrorName(status)); + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */