From 0101e2632c34c05f2e0cf6baedf219389aa2fb8a Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 28 Aug 2020 19:26:55 +0000 Subject: [PATCH] ICU-20164 Make NoUnit a zero-cost abstraction over MeasureUnit. See #1230 --- icu4c/source/i18n/i18n.vcxproj | 1 - icu4c/source/i18n/i18n.vcxproj.filters | 3 - icu4c/source/i18n/i18n_uwp.vcxproj | 1 - icu4c/source/i18n/measunit.cpp | 9 - icu4c/source/i18n/nounit.cpp | 42 ----- icu4c/source/i18n/number_formatimpl.cpp | 4 +- icu4c/source/i18n/number_skeletons.cpp | 40 ++--- icu4c/source/i18n/number_utils.h | 4 +- icu4c/source/i18n/sources.txt | 1 - icu4c/source/i18n/unicode/measunit.h | 6 - icu4c/source/i18n/unicode/nounit.h | 89 ++++------ icu4c/source/i18n/unicode/numberformatter.h | 4 +- icu4c/source/test/depstest/dependencies.txt | 2 +- icu4c/source/test/intltest/numbertest_api.cpp | 12 ++ icu4c/source/test/intltest/uobjtest.cpp | 2 - .../test/testdata/numberpermutationtest.txt | 158 +++++++++--------- .../ibm/icu/number/NumberFormatterImpl.java | 10 +- .../ibm/icu/number/NumberSkeletonImpl.java | 20 +-- .../src/com/ibm/icu/util/MeasureUnit.java | 9 - .../core/src/com/ibm/icu/util/NoUnit.java | 45 +++-- .../icu/dev/data/numberpermutationtest.txt | 158 +++++++++--------- .../test/number/NumberFormatterApiTest.java | 13 ++ 22 files changed, 269 insertions(+), 364 deletions(-) delete mode 100644 icu4c/source/i18n/nounit.cpp diff --git a/icu4c/source/i18n/i18n.vcxproj b/icu4c/source/i18n/i18n.vcxproj index 88083d2f5f7..e84cfbdace6 100644 --- a/icu4c/source/i18n/i18n.vcxproj +++ b/icu4c/source/i18n/i18n.vcxproj @@ -193,7 +193,6 @@ - diff --git a/icu4c/source/i18n/i18n.vcxproj.filters b/icu4c/source/i18n/i18n.vcxproj.filters index 9565f43da27..a4ad63a1edb 100644 --- a/icu4c/source/i18n/i18n.vcxproj.filters +++ b/icu4c/source/i18n/i18n.vcxproj.filters @@ -531,9 +531,6 @@ formatting - - misc - formatting diff --git a/icu4c/source/i18n/i18n_uwp.vcxproj b/icu4c/source/i18n/i18n_uwp.vcxproj index 3c6734b96ce..327e4985544 100644 --- a/icu4c/source/i18n/i18n_uwp.vcxproj +++ b/icu4c/source/i18n/i18n_uwp.vcxproj @@ -414,7 +414,6 @@ - diff --git a/icu4c/source/i18n/measunit.cpp b/icu4c/source/i18n/measunit.cpp index 8614f914d34..743032bdc62 100644 --- a/icu4c/source/i18n/measunit.cpp +++ b/icu4c/source/i18n/measunit.cpp @@ -2266,15 +2266,6 @@ void MeasureUnit::initCurrency(StringPiece isoCurrency) { fSubTypeId = result - gOffsets[fTypeId]; } -void MeasureUnit::initNoUnit(const char *subtype) { - int32_t result = binarySearch(gTypes, 0, UPRV_LENGTHOF(gTypes), "none"); - U_ASSERT(result != -1); - fTypeId = result; - result = binarySearch(gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], subtype); - U_ASSERT(result != -1); - fSubTypeId = result - gOffsets[fTypeId]; -} - void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) { fTypeId = typeId; fSubTypeId = subTypeId; diff --git a/icu4c/source/i18n/nounit.cpp b/icu4c/source/i18n/nounit.cpp deleted file mode 100644 index 1d4aa05506e..00000000000 --- a/icu4c/source/i18n/nounit.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// © 2017 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/nounit.h" -#include "uassert.h" - -#if !UCONFIG_NO_FORMATTING - -U_NAMESPACE_BEGIN - -UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NoUnit) - -NoUnit U_EXPORT2 NoUnit::base() { - return NoUnit(""); -} - -NoUnit U_EXPORT2 NoUnit::percent() { - return NoUnit("percent"); -} - -NoUnit U_EXPORT2 NoUnit::permille() { - return NoUnit("permille"); -} - -NoUnit::NoUnit(const char* subtype) { - initNoUnit(subtype); -} - -NoUnit::NoUnit(const NoUnit& other) : MeasureUnit(other) { -} - -NoUnit* NoUnit::clone() const { - return new NoUnit(*this); -} - -NoUnit::~NoUnit() { -} - - -U_NAMESPACE_END - -#endif diff --git a/icu4c/source/i18n/number_formatimpl.cpp b/icu4c/source/i18n/number_formatimpl.cpp index d5c3e6e4323..e6b1c5b929a 100644 --- a/icu4c/source/i18n/number_formatimpl.cpp +++ b/icu4c/source/i18n/number_formatimpl.cpp @@ -130,7 +130,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, // Pre-compute a few values for efficiency. bool isCurrency = utils::unitIsCurrency(macros.unit); - bool isNoUnit = utils::unitIsNoUnit(macros.unit); + bool isBaseUnit = utils::unitIsBaseUnit(macros.unit); bool isPercent = utils::unitIsPercent(macros.unit); bool isPermille = utils::unitIsPermille(macros.unit); bool isAccounting = @@ -144,7 +144,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) { unitWidth = macros.unitWidth; } - bool isCldrUnit = !isCurrency && !isNoUnit && + bool isCldrUnit = !isCurrency && !isBaseUnit && (unitWidth == UNUM_UNIT_WIDTH_FULL_NAME || !(isPercent || isPermille)); // Select the numbering system. diff --git a/icu4c/source/i18n/number_skeletons.cpp b/icu4c/source/i18n/number_skeletons.cpp index 66cae73be3c..58f7e2ce2ea 100644 --- a/icu4c/source/i18n/number_skeletons.cpp +++ b/icu4c/source/i18n/number_skeletons.cpp @@ -189,14 +189,11 @@ Notation stem_to_object::notation(skeleton::StemEnum stem) { MeasureUnit stem_to_object::unit(skeleton::StemEnum stem) { switch (stem) { case STEM_BASE_UNIT: - // Slicing is okay - return NoUnit::base(); // NOLINT + return MeasureUnit(); case STEM_PERCENT: - // Slicing is okay - return NoUnit::percent(); // NOLINT + return MeasureUnit::getPercent(); case STEM_PERMILLE: - // Slicing is okay - return NoUnit::permille(); // NOLINT + return MeasureUnit::getPermille(); default: UPRV_UNREACHABLE; } @@ -1521,17 +1518,15 @@ bool GeneratorHelpers::unit(const MacroProps& macros, UnicodeString& sb, UErrorC } blueprint_helpers::generateCurrencyOption(currency, sb, status); return true; - } else if (utils::unitIsNoUnit(macros.unit)) { - if (utils::unitIsPercent(macros.unit)) { - sb.append(u"percent", -1); - return true; - } else if (utils::unitIsPermille(macros.unit)) { - sb.append(u"permille", -1); - return true; - } else { - // Default value is not shown in normalized form - return false; - } + } else if (utils::unitIsBaseUnit(macros.unit)) { + // Default value is not shown in normalized form + return false; + } else if (utils::unitIsPercent(macros.unit)) { + sb.append(u"percent", -1); + return true; + } else if (utils::unitIsPermille(macros.unit)) { + sb.append(u"permille", -1); + return true; } else { sb.append(u"measure-unit/", -1); blueprint_helpers::generateMeasureUnitOption(macros.unit, sb, status); @@ -1541,14 +1536,9 @@ bool GeneratorHelpers::unit(const MacroProps& macros, UnicodeString& sb, UErrorC bool GeneratorHelpers::perUnit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { // Per-units are currently expected to be only MeasureUnits. - if (utils::unitIsNoUnit(macros.perUnit)) { - if (utils::unitIsPercent(macros.perUnit) || utils::unitIsPermille(macros.perUnit)) { - status = U_UNSUPPORTED_ERROR; - return false; - } else { - // Default value: ok to ignore - return false; - } + if (utils::unitIsBaseUnit(macros.perUnit)) { + // Default value: ok to ignore + return false; } else if (utils::unitIsCurrency(macros.perUnit)) { status = U_UNSUPPORTED_ERROR; return false; diff --git a/icu4c/source/i18n/number_utils.h b/icu4c/source/i18n/number_utils.h index 93195f080b2..bc369c940f7 100644 --- a/icu4c/source/i18n/number_utils.h +++ b/icu4c/source/i18n/number_utils.h @@ -49,8 +49,8 @@ inline bool unitIsCurrency(const MeasureUnit& unit) { return uprv_strcmp("currency", unit.getType()) == 0; } -inline bool unitIsNoUnit(const MeasureUnit& unit) { - return uprv_strcmp("none", unit.getType()) == 0; +inline bool unitIsBaseUnit(const MeasureUnit& unit) { + return unit == MeasureUnit(); } inline bool unitIsPercent(const MeasureUnit& unit) { diff --git a/icu4c/source/i18n/sources.txt b/icu4c/source/i18n/sources.txt index 335e5ee892a..faaa14ec4c1 100644 --- a/icu4c/source/i18n/sources.txt +++ b/icu4c/source/i18n/sources.txt @@ -97,7 +97,6 @@ nfrs.cpp nfrule.cpp nfsubs.cpp nortrans.cpp -nounit.cpp nultrans.cpp number_affixutils.cpp number_asformat.cpp diff --git a/icu4c/source/i18n/unicode/measunit.h b/icu4c/source/i18n/unicode/measunit.h index 310e4ed4005..0e7f8958003 100644 --- a/icu4c/source/i18n/unicode/measunit.h +++ b/icu4c/source/i18n/unicode/measunit.h @@ -3353,12 +3353,6 @@ class U_I18N_API MeasureUnit: public UObject { */ void initCurrency(StringPiece isoCurrency); - /** - * For ICU use only. - * @internal - */ - void initNoUnit(const char *subtype); - #endif /* U_HIDE_INTERNAL_API */ private: diff --git a/icu4c/source/i18n/unicode/nounit.h b/icu4c/source/i18n/unicode/nounit.h index 61b5c16ee39..cee45e352df 100644 --- a/icu4c/source/i18n/unicode/nounit.h +++ b/icu4c/source/i18n/unicode/nounit.h @@ -29,80 +29,53 @@ U_NAMESPACE_BEGIN /** * Dimensionless unit for percent and permille. + * Prior to ICU 68, this namespace was a class with the same name. * @see NumberFormatter - * @draft ICU 60 + * @draft ICU 68 */ -class U_I18N_API NoUnit: public MeasureUnit { -public: +namespace NoUnit { /** * Returns an instance for the base unit (dimensionless and no scaling). * - * @return a NoUnit instance - * @draft ICU 60 + * Prior to ICU 68, this function returned a NoUnit by value. + * + * Since ICU 68, this function returns the same value as the default MeasureUnit constructor. + * + * @return a MeasureUnit instance + * @draft ICU 68 */ - static NoUnit U_EXPORT2 base(); + static inline MeasureUnit U_EXPORT2 base() { + return MeasureUnit(); + } /** * Returns an instance for percent, or 1/100 of a base unit. * - * @return a NoUnit instance - * @draft ICU 60 + * Prior to ICU 68, this function returned a NoUnit by value. + * + * Since ICU 68, this function returns the same value as MeasureUnit::getPercent(). + * + * @return a MeasureUnit instance + * @draft ICU 68 */ - static NoUnit U_EXPORT2 percent(); + static inline MeasureUnit U_EXPORT2 percent() { + return MeasureUnit::getPercent(); + } /** * Returns an instance for permille, or 1/1000 of a base unit. * - * @return a NoUnit instance - * @draft ICU 60 + * Prior to ICU 68, this function returned a NoUnit by value. + * + * Since ICU 68, this function returns the same value as MeasureUnit::getPermille(). + * + * @return a MeasureUnit instance + * @draft ICU 68 */ - static NoUnit U_EXPORT2 permille(); - - /** - * Copy operator. - * @draft ICU 60 - */ - NoUnit(const NoUnit& other); - - /** - * Destructor. - * @draft ICU 60 - */ - virtual ~NoUnit(); - - /** - * Return a polymorphic clone of this object. The result will - * have the same class as returned by getDynamicClassID(). - * @draft ICU 60 - */ - virtual NoUnit* clone() const; - - /** - * Returns a unique class ID for this object POLYMORPHICALLY. - * This method implements a simple form of RTTI used by ICU. - * @return The class ID for this object. All objects of a given - * class have the same class ID. Objects of other classes have - * different class IDs. - * @draft ICU 60 - */ - virtual UClassID getDynamicClassID() const; - - /** - * Returns the class ID for this class. This is used to compare to - * the return value of getDynamicClassID(). - * @return The class ID for all objects of this class. - * @draft ICU 60 - */ - static UClassID U_EXPORT2 getStaticClassID(); - -private: - /** - * Constructor - * @internal (private) - */ - NoUnit(const char* subtype); - -}; + static inline MeasureUnit U_EXPORT2 permille() { + return MeasureUnit::getPermille(); + } +} U_NAMESPACE_END diff --git a/icu4c/source/i18n/unicode/numberformatter.h b/icu4c/source/i18n/unicode/numberformatter.h index 08f93cd6cfa..6ac33b47878 100644 --- a/icu4c/source/i18n/unicode/numberformatter.h +++ b/icu4c/source/i18n/unicode/numberformatter.h @@ -1373,10 +1373,10 @@ struct U_I18N_API MacroProps : public UMemory { Notation notation; /** @internal */ - MeasureUnit unit; // = NoUnit::base(); + MeasureUnit unit; // = MeasureUnit(); (the base dimensionless unit) /** @internal */ - MeasureUnit perUnit; // = NoUnit::base(); + MeasureUnit perUnit; // = MeasureUnit(); (the base dimensionless unit) /** @internal */ Precision precision; // = Precision(); (bogus) diff --git a/icu4c/source/test/depstest/dependencies.txt b/icu4c/source/test/depstest/dependencies.txt index 9dfad52daec..82e2d441565 100644 --- a/icu4c/source/test/depstest/dependencies.txt +++ b/icu4c/source/test/depstest/dependencies.txt @@ -1068,7 +1068,7 @@ group: units_extra units bytestriebuilder bytestrie resourcebundle uclean_i18n group: units - measunit.o currunit.o nounit.o + measunit.o currunit.o deps stringenumeration errorcode diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp index ad7a2991d98..75b0d006569 100644 --- a/icu4c/source/test/intltest/numbertest_api.cpp +++ b/icu4c/source/test/intltest/numbertest_api.cpp @@ -1013,6 +1013,18 @@ void NumberFormatterApiTest::unitPercent() { Locale::getEnglish(), -98.7654321, u"-98.765432%"); + + assertFormatSingle( + u"Per Percent", + u"measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name", + u"measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name", + NumberFormatter::with() + .unit(MeasureUnit::getMeter()) + .perUnit(MeasureUnit::getPercent()) + .unitWidth(UNUM_UNIT_WIDTH_FULL_NAME), + Locale::getEnglish(), + 50, + u"50 meters per percent"); } void NumberFormatterApiTest::percentParity() { diff --git a/icu4c/source/test/intltest/uobjtest.cpp b/icu4c/source/test/intltest/uobjtest.cpp index 3c4abb0dad0..6b6a02c3962 100644 --- a/icu4c/source/test/intltest/uobjtest.cpp +++ b/icu4c/source/test/intltest/uobjtest.cpp @@ -276,7 +276,6 @@ UObject *UObjectTest::testClassNoClassID(UObject *obj, const char *className, co #include "unicode/msgfmt.h" #include "unicode/normlzr.h" #include "unicode/normalizer2.h" -#include "unicode/nounit.h" #include "unicode/numfmt.h" #include "unicode/parsepos.h" #include "unicode/plurrule.h" @@ -373,7 +372,6 @@ void UObjectTest::testIDs() TESTCLASSID_DEFAULT(Formattable); TESTCLASSID_FACTORY(MeasureUnit, MeasureUnit::createMeter(status)); - TESTCLASSID_FACTORY(NoUnit, NoUnit::percent().clone()); TESTCLASSID_FACTORY(TimeUnit, TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR, status)); static const UChar SMALL_STR[] = u"QQQ"; TESTCLASSID_CTOR(CurrencyAmount, (1.0, SMALL_STR, status)); diff --git a/icu4c/source/test/testdata/numberpermutationtest.txt b/icu4c/source/test/testdata/numberpermutationtest.txt index 24136ad1016..e5f0b78ee80 100644 --- a/icu4c/source/test/testdata/numberpermutationtest.txt +++ b/icu4c/source/test/testdata/numberpermutationtest.txt @@ -17,17 +17,17 @@ compact-short percent unit-width-narrow compact-short percent unit-width-full-name es-MX - 0 % - 92 k - -0.22 % + 0 por ciento + 92 k por ciento + -0.22 por ciento zh-TW 0% - 9.2萬 + 9.2萬% -0.22% bn-BD - ০% - ৯২ হা - -০.২২% + ০শতাংশ + ৯২ হাশতাংশ + -০.২২শতাংশ compact-short currency/EUR unit-width-narrow es-MX @@ -101,17 +101,17 @@ scientific/+ee/sign-always percent unit-width-narrow scientific/+ee/sign-always percent unit-width-full-name es-MX - 0E+00 % - 9.182736E+04 % - -2.2222E-01 % + 0E+00 por ciento + 9.182736E+04 por ciento + -2.2222E-01 por ciento zh-TW 0E+00% 9.182736E+04% -2.2222E-01% bn-BD - ০E+০০% - ৯.১৮২৭৩৬E+০৪% - -২.২২২২E-০১% + ০E+০০শতাংশ + ৯.১৮২৭৩৬E+০৪শতাংশ + -২.২২২২E-০১শতাংশ scientific/+ee/sign-always currency/EUR unit-width-narrow es-MX @@ -3139,59 +3139,59 @@ percent unit-width-narrow @@ percent unit-width-full-name precision-integer es-MX - 0 % - 91,827 % - -0 % + 0 por ciento + 91,827 por ciento + -0 por ciento zh-TW 0% 91,827% -0% bn-BD - ০% - ৯১,৮২৭% - -০% + ০শতাংশ + ৯১,৮২৭শতাংশ + -০শতাংশ percent unit-width-full-name .000 es-MX - 0.000 % - 91,827.364 % - -0.222 % + 0.000 por ciento + 91,827.364 por ciento + -0.222 por ciento zh-TW 0.000% 91,827.364% -0.222% bn-BD - ০.০০০% - ৯১,৮২৭.৩৬৪% - -০.২২২% + ০.০০০শতাংশ + ৯১,৮২৭.৩৬৪শতাংশ + -০.২২২শতাংশ percent unit-width-full-name .##/@@@+ es-MX - 0 % - 91,827.36 % - -0.222 % + 0 por ciento + 91,827.36 por ciento + -0.222 por ciento zh-TW 0% 91,827.36% -0.222% bn-BD - ০% - ৯১,৮২৭.৩৬% - -০.২২২% + ০শতাংশ + ৯১,৮২৭.৩৬শতাংশ + -০.২২২শতাংশ percent unit-width-full-name @@ es-MX - 0.0 % - 92,000 % - -0.22 % + 0.0 por ciento + 92,000 por ciento + -0.22 por ciento zh-TW 0.0% 92,000% -0.22% bn-BD - ০.০% - ৯২,০০০% - -০.২২% + ০.০শতাংশ + ৯২,০০০শতাংশ + -০.২২শতাংশ currency/EUR unit-width-narrow precision-integer es-MX @@ -3433,17 +3433,17 @@ percent unit-width-narrow rounding-mode-floor percent unit-width-full-name rounding-mode-floor es-MX - 0 % - 91,827.3645 % - -0.22222 % + 0 por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% 91,827.3645% -0.22222% bn-BD - ০% - ৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০শতাংশ + ৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow rounding-mode-floor es-MX @@ -3517,17 +3517,17 @@ percent unit-width-narrow integer-width/##00 percent unit-width-full-name integer-width/##00 es-MX - 00 % - 1827.3645 % - -00.22222 % + 00 por ciento + 1827.3645 por ciento + -00.22222 por ciento zh-TW 00% 1,827.3645% -00.22222% bn-BD - ০০% - ১,৮২৭.৩৬৪৫% - -০০.২২২২২% + ০০শতাংশ + ১,৮২৭.৩৬৪৫শতাংশ + -০০.২২২২২শতাংশ currency/EUR unit-width-narrow integer-width/##00 es-MX @@ -3601,17 +3601,17 @@ percent unit-width-narrow scale/0.5 percent unit-width-full-name scale/0.5 es-MX - 0 % - 45,913.68225 % - -0.11111 % + 0 por ciento + 45,913.68225 por ciento + -0.11111 por ciento zh-TW 0% 45,913.68225% -0.11111% bn-BD - ০% - ৪৫,৯১৩.৬৮২২৫% - -০.১১১১১% + ০শতাংশ + ৪৫,৯১৩.৬৮২২৫শতাংশ + -০.১১১১১শতাংশ currency/EUR unit-width-narrow scale/0.5 es-MX @@ -3685,17 +3685,17 @@ percent unit-width-narrow group-on-aligned percent unit-width-full-name group-on-aligned es-MX - 0 % - 91,827.3645 % - -0.22222 % + 0 por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% 91,827.3645% -0.22222% bn-BD - ০% - ৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০শতাংশ + ৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow group-on-aligned es-MX @@ -3769,17 +3769,17 @@ percent unit-width-narrow latin percent unit-width-full-name latin es-MX - 0 % - 91,827.3645 % - -0.22222 % + 0 por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% 91,827.3645% -0.22222% bn-BD - 0% - 91,827.3645% - -0.22222% + 0শতাংশ + 91,827.3645শতাংশ + -0.22222শতাংশ currency/EUR unit-width-narrow latin es-MX @@ -3853,17 +3853,17 @@ percent unit-width-narrow sign-accounting-except-zero percent unit-width-full-name sign-accounting-except-zero es-MX - 0 % - +91,827.3645 % - -0.22222 % + 0 por ciento + +91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% +91,827.3645% -0.22222% bn-BD - ০% - +৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০শতাংশ + +৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow sign-accounting-except-zero es-MX @@ -3937,17 +3937,17 @@ percent unit-width-narrow decimal-always percent unit-width-full-name decimal-always es-MX - 0. % - 91,827.3645 % - -0.22222 % + 0. por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0.% 91,827.3645% -0.22222% bn-BD - ০.% - ৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০.শতাংশ + ৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow decimal-always es-MX diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java index e0233f2b453..629732e4994 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java @@ -146,10 +146,8 @@ class NumberFormatterImpl { return unit != null && "currency".equals(unit.getType()); } - private static boolean unitIsNoUnit(MeasureUnit unit) { - // NOTE: In ICU4C, units cannot be null, and the default unit is a NoUnit. - // In ICU4J, return TRUE for a null unit from this method. - return unit == null || "none".equals(unit.getType()); + private static boolean unitIsBaseUnit(MeasureUnit unit) { + return unit == null; } private static boolean unitIsPercent(MeasureUnit unit) { @@ -181,7 +179,7 @@ class NumberFormatterImpl { // Pre-compute a few values for efficiency. boolean isCurrency = unitIsCurrency(macros.unit); - boolean isNoUnit = unitIsNoUnit(macros.unit); + boolean isBaseUnit = unitIsBaseUnit(macros.unit); boolean isPercent = unitIsPercent(macros.unit); boolean isPermille = unitIsPermille(macros.unit); boolean isAccounting = macros.sign == SignDisplay.ACCOUNTING @@ -192,7 +190,7 @@ class NumberFormatterImpl { if (macros.unitWidth != null) { unitWidth = macros.unitWidth; } - boolean isCldrUnit = !isCurrency && !isNoUnit && + boolean isCldrUnit = !isCurrency && !isBaseUnit && (unitWidth == UnitWidth.FULL_NAME || !(isPercent || isPermille)); PluralRules rules = macros.rules; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java index 33e60f7b735..e9ace799e85 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java @@ -1436,18 +1436,12 @@ class NumberSkeletonImpl { sb.append("currency/"); BlueprintHelpers.generateCurrencyOption((Currency) macros.unit, sb); return true; - } else if (macros.unit instanceof NoUnit) { - if (macros.unit == NoUnit.PERCENT) { - sb.append("percent"); - return true; - } else if (macros.unit == NoUnit.PERMILLE) { - sb.append("permille"); - return true; - } else { - assert macros.unit == NoUnit.BASE; - // Default value is not shown in normalized form - return false; - } + } else if (macros.unit == MeasureUnit.PERCENT) { + sb.append("percent"); + return true; + } else if (macros.unit == MeasureUnit.PERMILLE) { + sb.append("permille"); + return true; } else { sb.append("measure-unit/"); BlueprintHelpers.generateMeasureUnitOption(macros.unit, sb); @@ -1457,7 +1451,7 @@ class NumberSkeletonImpl { private static boolean perUnit(MacroProps macros, StringBuilder sb) { // Per-units are currently expected to be only MeasureUnits. - if (macros.perUnit instanceof Currency || macros.perUnit instanceof NoUnit) { + if (macros.perUnit instanceof Currency) { throw new UnsupportedOperationException( "Cannot generate number skeleton with per-unit that is not a standard measure unit"); } else { diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java b/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java index 356ca9946fe..20a78503d0e 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java @@ -197,8 +197,6 @@ public class MeasureUnit implements Serializable { factory = CURRENCY_FACTORY; } else if ("duration".equals(type)) { factory = TIMEUNIT_FACTORY; - } else if ("none".equals(type)) { - factory = NOUNIT_FACTORY; } else { factory = UNIT_FACTORY; } @@ -294,13 +292,6 @@ public class MeasureUnit implements Serializable { } }; - static Factory NOUNIT_FACTORY = new Factory() { - @Override - public MeasureUnit create(String type, String subType) { - return new NoUnit(subType); - } - }; - /** * Sink for enumerating the available measure units. */ diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java b/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java index 7a0aba84ae2..a767e62f5da 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java @@ -7,47 +7,46 @@ import com.ibm.icu.number.NumberFormatter; /** * Dimensionless unit for percent and permille. * @see NumberFormatter - * @draft ICU 60 + * @draft ICU 68 * @provisional This API might change or be removed in a future release. */ -public class NoUnit extends MeasureUnit { - private static final long serialVersionUID = 2467174286237024095L; - +public final class NoUnit { /** * Constant for the base unit (dimensionless and no scaling). * - * @draft ICU 60 + * Prior to ICU 68, this constant equaled an instance of NoUnit. + * + * Since ICU 68, this constant equals null. + * + * @draft ICU 68 * @provisional This API might change or be removed in a future release. */ - public static final NoUnit BASE = - (NoUnit) MeasureUnit.internalGetInstance("none", "base"); + public static final MeasureUnit BASE = null; /** * Constant for the percent unit, or 1/100 of a base unit. * - * @draft ICU 60 + * Prior to ICU 68, this constant equaled an instance of NoUnit. + * + * Since ICU 68, this constant is equivalent to MeasureUnit.PERCENT. + * + * @draft ICU 68 * @provisional This API might change or be removed in a future release. */ - public static final NoUnit PERCENT = - (NoUnit) MeasureUnit.internalGetInstance("none", "percent"); + public static final MeasureUnit PERCENT = MeasureUnit.PERCENT; /** * Constant for the permille unit, or 1/100 of a base unit. * - * @draft ICU 60 + * Prior to ICU 68, this constant equaled an instance of NoUnit. + * + * Since ICU 68, this constant is equivalent to MeasureUnit.PERMILLE. + * + * @draft ICU 68 * @provisional This API might change or be removed in a future release. */ - public static final NoUnit PERMILLE = - (NoUnit) MeasureUnit.internalGetInstance("none", "permille"); + public static final MeasureUnit PERMILLE = MeasureUnit.PERMILLE; - - /** - * Package local constructor. This class is not designed for subclassing - * by ICU users. - * - * @param subType The unit subtype. - */ - NoUnit(String subType) { - super("none", subType); - } + // This class is a namespace not intended to be instantiated: + private NoUnit() {} } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt index 24136ad1016..e5f0b78ee80 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt @@ -17,17 +17,17 @@ compact-short percent unit-width-narrow compact-short percent unit-width-full-name es-MX - 0 % - 92 k - -0.22 % + 0 por ciento + 92 k por ciento + -0.22 por ciento zh-TW 0% - 9.2萬 + 9.2萬% -0.22% bn-BD - ০% - ৯২ হা - -০.২২% + ০শতাংশ + ৯২ হাশতাংশ + -০.২২শতাংশ compact-short currency/EUR unit-width-narrow es-MX @@ -101,17 +101,17 @@ scientific/+ee/sign-always percent unit-width-narrow scientific/+ee/sign-always percent unit-width-full-name es-MX - 0E+00 % - 9.182736E+04 % - -2.2222E-01 % + 0E+00 por ciento + 9.182736E+04 por ciento + -2.2222E-01 por ciento zh-TW 0E+00% 9.182736E+04% -2.2222E-01% bn-BD - ০E+০০% - ৯.১৮২৭৩৬E+০৪% - -২.২২২২E-০১% + ০E+০০শতাংশ + ৯.১৮২৭৩৬E+০৪শতাংশ + -২.২২২২E-০১শতাংশ scientific/+ee/sign-always currency/EUR unit-width-narrow es-MX @@ -3139,59 +3139,59 @@ percent unit-width-narrow @@ percent unit-width-full-name precision-integer es-MX - 0 % - 91,827 % - -0 % + 0 por ciento + 91,827 por ciento + -0 por ciento zh-TW 0% 91,827% -0% bn-BD - ০% - ৯১,৮২৭% - -০% + ০শতাংশ + ৯১,৮২৭শতাংশ + -০শতাংশ percent unit-width-full-name .000 es-MX - 0.000 % - 91,827.364 % - -0.222 % + 0.000 por ciento + 91,827.364 por ciento + -0.222 por ciento zh-TW 0.000% 91,827.364% -0.222% bn-BD - ০.০০০% - ৯১,৮২৭.৩৬৪% - -০.২২২% + ০.০০০শতাংশ + ৯১,৮২৭.৩৬৪শতাংশ + -০.২২২শতাংশ percent unit-width-full-name .##/@@@+ es-MX - 0 % - 91,827.36 % - -0.222 % + 0 por ciento + 91,827.36 por ciento + -0.222 por ciento zh-TW 0% 91,827.36% -0.222% bn-BD - ০% - ৯১,৮২৭.৩৬% - -০.২২২% + ০শতাংশ + ৯১,৮২৭.৩৬শতাংশ + -০.২২২শতাংশ percent unit-width-full-name @@ es-MX - 0.0 % - 92,000 % - -0.22 % + 0.0 por ciento + 92,000 por ciento + -0.22 por ciento zh-TW 0.0% 92,000% -0.22% bn-BD - ০.০% - ৯২,০০০% - -০.২২% + ০.০শতাংশ + ৯২,০০০শতাংশ + -০.২২শতাংশ currency/EUR unit-width-narrow precision-integer es-MX @@ -3433,17 +3433,17 @@ percent unit-width-narrow rounding-mode-floor percent unit-width-full-name rounding-mode-floor es-MX - 0 % - 91,827.3645 % - -0.22222 % + 0 por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% 91,827.3645% -0.22222% bn-BD - ০% - ৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০শতাংশ + ৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow rounding-mode-floor es-MX @@ -3517,17 +3517,17 @@ percent unit-width-narrow integer-width/##00 percent unit-width-full-name integer-width/##00 es-MX - 00 % - 1827.3645 % - -00.22222 % + 00 por ciento + 1827.3645 por ciento + -00.22222 por ciento zh-TW 00% 1,827.3645% -00.22222% bn-BD - ০০% - ১,৮২৭.৩৬৪৫% - -০০.২২২২২% + ০০শতাংশ + ১,৮২৭.৩৬৪৫শতাংশ + -০০.২২২২২শতাংশ currency/EUR unit-width-narrow integer-width/##00 es-MX @@ -3601,17 +3601,17 @@ percent unit-width-narrow scale/0.5 percent unit-width-full-name scale/0.5 es-MX - 0 % - 45,913.68225 % - -0.11111 % + 0 por ciento + 45,913.68225 por ciento + -0.11111 por ciento zh-TW 0% 45,913.68225% -0.11111% bn-BD - ০% - ৪৫,৯১৩.৬৮২২৫% - -০.১১১১১% + ০শতাংশ + ৪৫,৯১৩.৬৮২২৫শতাংশ + -০.১১১১১শতাংশ currency/EUR unit-width-narrow scale/0.5 es-MX @@ -3685,17 +3685,17 @@ percent unit-width-narrow group-on-aligned percent unit-width-full-name group-on-aligned es-MX - 0 % - 91,827.3645 % - -0.22222 % + 0 por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% 91,827.3645% -0.22222% bn-BD - ০% - ৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০শতাংশ + ৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow group-on-aligned es-MX @@ -3769,17 +3769,17 @@ percent unit-width-narrow latin percent unit-width-full-name latin es-MX - 0 % - 91,827.3645 % - -0.22222 % + 0 por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% 91,827.3645% -0.22222% bn-BD - 0% - 91,827.3645% - -0.22222% + 0শতাংশ + 91,827.3645শতাংশ + -0.22222শতাংশ currency/EUR unit-width-narrow latin es-MX @@ -3853,17 +3853,17 @@ percent unit-width-narrow sign-accounting-except-zero percent unit-width-full-name sign-accounting-except-zero es-MX - 0 % - +91,827.3645 % - -0.22222 % + 0 por ciento + +91,827.3645 por ciento + -0.22222 por ciento zh-TW 0% +91,827.3645% -0.22222% bn-BD - ০% - +৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০শতাংশ + +৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow sign-accounting-except-zero es-MX @@ -3937,17 +3937,17 @@ percent unit-width-narrow decimal-always percent unit-width-full-name decimal-always es-MX - 0. % - 91,827.3645 % - -0.22222 % + 0. por ciento + 91,827.3645 por ciento + -0.22222 por ciento zh-TW 0.% 91,827.3645% -0.22222% bn-BD - ০.% - ৯১,৮২৭.৩৬৪৫% - -০.২২২২২% + ০.শতাংশ + ৯১,৮২৭.৩৬৪৫শতাংশ + -০.২২২২২শতাংশ currency/EUR unit-width-narrow decimal-always es-MX diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java index 3056545315a..d3bbc13e90c 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java @@ -966,6 +966,19 @@ public class NumberFormatterApiTest { ULocale.ENGLISH, -98.7654321, "-98.765432%"); + + assertFormatSingle( + "Per Percent", + "measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name", + "measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name", + NumberFormatter.with() + .unit(MeasureUnit.METER) + .perUnit(MeasureUnit.PERCENT) + .unitWidth(UnitWidth.FULL_NAME), + ULocale.ENGLISH, + 50, + "50 meters per percent"); + } @Test